home *** CD-ROM | disk | FTP | other *** search
/ Linux Cubed Series 8: LINUX Games / Linux Cubed Series 8 - LINUX Games.iso / games / actionrp / angband_.5 / angband_ / src / moria2.c < prev    next >
C/C++ Source or Header  |  1994-04-22  |  85KB  |  2,990 lines

  1. /*
  2.  * moria2.c: misc code, mainly to handle player commands 
  3.  *
  4.  * Copyright (c) 1989 James E. Wilson, Robert A. Koeneke 
  5.  *
  6.  * This software may be copied and distributed for educational, research, and
  7.  * not for profit purposes provided that this copyright and statement are
  8.  * included in all such copies. 
  9.  */
  10.  
  11. #include <ctype.h>
  12.  
  13. #include "constant.h"
  14. #include "monster.h"
  15. #include "config.h"
  16. #include "types.h"
  17. #include "externs.h"
  18.  
  19. #ifdef USG
  20. #ifndef ATARIST_MWC
  21. #include <string.h>
  22. #endif
  23. #else
  24. #include <strings.h>
  25. #endif
  26.  
  27. /* Lets do all prototypes correctly.... -CWS */
  28. #ifndef NO_LINT_ARGS
  29. #ifdef __STDC__
  30. static int look_ray(int, int, int);
  31. static int look_see(int, int, int *);
  32. static void hit_trap(int, int);
  33. static int summon_object(int, int, int, int, int32u);
  34. static void py_attack(int, int);
  35. static void chest_trap(int, int);
  36. static void inven_throw(int, struct inven_type *);
  37. static void facts(struct inven_type *, int *, int *, int *, int *, int *);
  38. static void drop_throw(int, int, struct inven_type *);
  39. static void py_bash(int, int);
  40. static const char *look_mon_desc(int);
  41. static int fearless(creature_type *);
  42.  
  43. #else
  44. static int          look_ray();
  45. static int          look_see();
  46. static void         hit_trap();
  47. static int          summon_object();
  48. static void         py_attack();
  49. static void         chest_trap();
  50. static void         inven_throw();
  51. static void         facts();
  52. static void         drop_throw();
  53. static void         py_bash();
  54. static const char   *look_mon_desc();
  55. static int          fearless();
  56.  
  57. #endif
  58. #endif
  59.  
  60.  
  61. /* Player hit a trap.    (Chuckle)            -RAK-     */
  62. static void 
  63. hit_trap(y, x)
  64.     int                 y, x;
  65. {
  66.     int                 i, ty, tx, num, dam;
  67.     register cave_type *c_ptr;
  68.     register struct misc *p_ptr;
  69.     register inven_type *t_ptr;
  70.     bigvtype            tmp;
  71.  
  72.     end_find();
  73.     change_trap(y, x);
  74.     c_ptr = &cave[y][x];
  75.     p_ptr = &py.misc;
  76.     t_ptr = &t_list[c_ptr->tptr];
  77.     dam = pdamroll(t_ptr->damage);
  78.     switch (t_ptr->subval) {
  79.       case 1:               /* Open pit */
  80.     msg_print("You fell into a pit!");
  81.     if (py.flags.ffall)
  82.         msg_print("You gently float down.");
  83.     else {
  84.         objdes(tmp, t_ptr, TRUE);
  85.         take_hit(dam, tmp);
  86.     }
  87.     break;
  88.       case 2:               /* Arrow trap */
  89.     if (test_hit(125, 0, 0, p_ptr->pac + p_ptr->ptoac, CLA_MISC_HIT)) {
  90.         objdes(tmp, t_ptr, TRUE);
  91.         take_hit(dam, tmp);
  92.         msg_print("An arrow hits you.");
  93.     } else
  94.         msg_print("An arrow barely misses you.");
  95.     break;
  96.       case 3:               /* Covered pit */
  97.     msg_print("You fell into a covered pit.");
  98.     if (py.flags.ffall)
  99.         msg_print("You gently float down.");
  100.     else {
  101.         objdes(tmp, t_ptr, TRUE);
  102.         take_hit(dam, tmp);
  103.     }
  104.     place_trap(y, x, 0);
  105.     break;
  106.       case 4:               /* Trap door */
  107.     if (!is_quest(dun_level)) {/* that would be too easy... -CFT */
  108.         msg_print("You fell through a trap door!");
  109.         new_level_flag = TRUE;
  110.         dun_level++;
  111.         if (py.flags.ffall)
  112.         msg_print("You gently float down.");
  113.         else {
  114.         objdes(tmp, t_ptr, TRUE);
  115.         take_hit(dam, tmp);
  116.         }
  117.         msg_print(NULL);       /* make sure can see the message before new level */
  118.     }
  119.      /* end normal */ 
  120.     else {               /* it's a quest level, can't let them fall through */
  121.         msg_print("You fall into a spiked pit!");
  122.         if (py.flags.ffall)
  123.         msg_print("You gently float down.");
  124.         else {
  125.         dam = (dam * 3) / 2;    /* do a little extra damage for spikes */
  126.         if (randint(3) == 1) {
  127.             msg_print("The spikes are poisoned!");
  128.             if (!(py.flags.poison_im || py.flags.poison_resist ||
  129.               py.flags.resist_poison))
  130.             dam *= 2;  /* more damage from poison!  :-)  -CFT */
  131.             else
  132.             msg_print("You are unaffected by the poison.");
  133.         }
  134.         } /* no ffall */
  135.     }
  136.     break;
  137.       case 5:               /* Sleep gas */
  138.     if (py.flags.paralysis == 0) {
  139.         msg_print("A strange white mist surrounds you!");
  140.         if (py.flags.free_act)
  141.         msg_print("You are unaffected.");
  142.         else {
  143.         msg_print("You fall asleep.");
  144.         py.flags.paralysis += randint(10) + 4;
  145.         }
  146.     }
  147.     break;
  148.       case 6:               /* Hid Obj */
  149.     (void)delete_object(y, x);
  150.     place_object(y, x);
  151.     msg_print("Hmmm, there was something under this rock.");
  152.     break;
  153.       case 7:               /* STR Dart */
  154.     if (test_hit(125, 0, 0, p_ptr->pac + p_ptr->ptoac, CLA_MISC_HIT)) {
  155.         if (!py.flags.sustain_str) {
  156.         (void)dec_stat(A_STR);
  157.         objdes(tmp, t_ptr, TRUE);
  158.         take_hit(dam, tmp);
  159.         msg_print("A small dart weakens you!");
  160.         } else
  161.         msg_print("A small dart hits you.");
  162.     } else
  163.         msg_print("A small dart barely misses you.");
  164.     break;
  165.       case 8:               /* Teleport */
  166.     teleport_flag = TRUE;
  167.     msg_print("You hit a teleport trap!");
  168.     /* Light up the teleport trap, before we teleport away.  */
  169.     move_light(y, x, y, x);
  170.     break;
  171.       case 9:               /* Rockfall */
  172.     take_hit(dam, "a falling rock");
  173.     (void)delete_object(y, x);
  174.     place_rubble(y, x);
  175.     msg_print("You are hit by falling rock.");
  176.     break;
  177.       case 10:               /* Corrode gas */
  178.     msg_print("A strange red gas surrounds you.");
  179.     corrode_gas("corrosion gas");
  180.     break;
  181.       case 11:               /* Summon mon */
  182.     (void)delete_object(y, x); /* Rune disappears.    */
  183.     num = 2 + randint(3);
  184.     for (i = 0; i < num; i++) {
  185.         ty = y;
  186.         tx = x;
  187.         (void)summon_monster(&ty, &tx, FALSE);
  188.     }
  189.     break;
  190.       case 12:               /* Fire trap */
  191.     msg_print("You are enveloped in flames!");
  192.     fire_dam(dam, "a fire trap");
  193.     break;
  194.       case 13:               /* Acid trap */
  195.     msg_print("You are splashed with acid!");
  196.     acid_dam(dam, "an acid trap");
  197.     break;
  198.       case 14:               /* Poison gas */
  199.     if (!(py.flags.poison_im || py.flags.poison_resist ||
  200.           py.flags.resist_poison))
  201.         poison_gas(dam, "a poison gas trap");
  202.     msg_print("A pungent green gas surrounds you!");
  203.     break;
  204.       case 15:               /* Blind Gas */
  205.     msg_print("A black gas surrounds you!");
  206.     if (!py.flags.blindness_resist)
  207.         py.flags.blind += randint(50) + 50;
  208.     break;
  209.       case 16:               /* Confuse Gas */
  210.     msg_print("A gas of scintillating colors surrounds you!");
  211.     if ((!py.flags.confusion_resist) && (!py.flags.chaos_resist))
  212.         py.flags.confused += randint(15) + 15;
  213.     break;
  214.       case 17:               /* Slow Dart */
  215.     if (test_hit(125, 0, 0, p_ptr->pac + p_ptr->ptoac, CLA_MISC_HIT)) {
  216.         objdes(tmp, t_ptr, TRUE);
  217.         take_hit(dam, tmp);
  218.         msg_print("A small dart hits you!");
  219.         if (py.flags.free_act)
  220.         msg_print("You are unaffected.");
  221.         else
  222.         py.flags.slow += randint(20) + 10;
  223.     } else
  224.         msg_print("A small dart barely misses you.");
  225.     break;
  226.       case 18:               /* CON Dart */
  227.     if (test_hit(125, 0, 0, p_ptr->pac + p_ptr->ptoac, CLA_MISC_HIT)) {
  228.         if (!py.flags.sustain_con) {
  229.         (void)dec_stat(A_CON);
  230.         objdes(tmp, t_ptr, TRUE);
  231.         take_hit(dam, tmp);
  232.         msg_print("A small dart saps your health!");
  233.         } else
  234.         msg_print("A small dart hits you.");
  235.     } else
  236.         msg_print("A small dart barely misses you.");
  237.     break;
  238.       case 19:               /* Secret Door */
  239.     break;
  240.       case 99:               /* Scare Mon */
  241.     break;
  242.  
  243.     /* Town level traps are special,    the stores.     */
  244.       case 101:
  245.       case 102:
  246.       case 103:
  247.       case 104:
  248.       case 105:
  249.       case 106:
  250.       case 107:
  251.       case 108:
  252.     enter_store(t_ptr->subval - 101);
  253.     break;
  254.  
  255.       default:
  256.     msg_print("Unknown trap value.");
  257.     break;
  258.     }
  259. }
  260.  
  261.  
  262. /* Return spell number and failure chance        -RAK-     */
  263. /*
  264.  * returns -1 if no spells in book returns 1 if choose a spell in book to
  265.  * cast returns 0 if don't choose a spell, i.e. exit with an escape 
  266.  */
  267. int 
  268. cast_spell(prompt, item_val, sn, sc)
  269.     const char         *prompt;
  270.     int                 item_val;
  271.     int                *sn, *sc;
  272. {
  273.     int32u              j1, j2;
  274.     register int        i, k;
  275.     int                 spell[63], result, first_spell;
  276.     register spell_type *s_ptr;
  277.  
  278.     if (!py.misc.pclass)
  279.     return 0;           /* if a warrior, abort as if by ESC -CFT */
  280.     result = (-1);
  281.     i = 0;
  282.     j1 = inventory[item_val].flags;
  283.     j2 = inventory[item_val].flags2;
  284.     first_spell = bit_pos(&j1);
  285. /* set j1 again, since bit_pos modified it */
  286.     j1 = inventory[item_val].flags & spell_learned;
  287.     s_ptr = magic_spell[py.misc.pclass - 1];
  288.     while (j1) {
  289.     k = bit_pos(&j1);
  290.     if (s_ptr[k].slevel <= py.misc.lev) {
  291.         spell[i] = k;
  292.         i++;
  293.     }
  294.     }
  295.     if (!(inventory[item_val].flags & spell_learned))
  296.     first_spell = bit_pos(&j2) + 32;
  297.     j2 = inventory[item_val].flags2 & spell_learned2;
  298.     while (j2) {
  299.     k = bit_pos(&j2);
  300.     if (s_ptr[k + 32].slevel <= py.misc.lev) {
  301.         spell[i] = k + 32;
  302.         i++;
  303.     }
  304.     }
  305.     if (i > 0) {
  306.     result = get_spell(spell, i, sn, sc, prompt, first_spell);
  307.     if (result && magic_spell[py.misc.pclass - 1][*sn].smana > py.misc.cmana) {
  308.         if (class[py.misc.pclass].spell == MAGE)
  309.         result = get_check("You summon your limited strength to cast this one! Confirm?");
  310.         else
  311.         result = get_check("The gods may think you presumptuous for this! Confirm?");
  312.     }
  313.     }
  314.     return (result);
  315. }
  316.  
  317.  
  318. /* Player is on an object.  Many things can happen based -RAK-     */
  319. /* on the TVAL of the object.  Traps are set off, money and most */
  320. /* objects are picked up.  Some objects, such as open doors, just */
  321. /* sit there.                               */
  322. void 
  323. carry(y, x, pickup)
  324.     int                 y, x;
  325.     int                 pickup;
  326. {
  327.     register int        locn, i;
  328.     bigvtype            out_val, tmp_str;
  329.     register cave_type *c_ptr;
  330.     register inven_type *i_ptr;
  331.  
  332.     c_ptr = &cave[y][x];
  333.     i_ptr = &t_list[c_ptr->tptr];
  334.     i = t_list[c_ptr->tptr].tval;
  335.     if (i <= TV_MAX_PICK_UP) {
  336.     end_find();
  337.     /* There's GOLD in them thar hills!      */
  338.     if (i == TV_GOLD) {
  339.         py.misc.au += i_ptr->cost;
  340.         objdes(tmp_str, i_ptr, TRUE);
  341.         (void)sprintf(out_val,
  342.               "You have found %ld gold pieces worth of %s.",
  343.               i_ptr->cost, tmp_str);
  344.         prt_gold();
  345.         (void)delete_object(y, x);
  346.         msg_print(out_val);
  347.     } else {
  348.         if (pickup && inven_check_num(i_ptr)) { /* Too many objects? */
  349.         if (carry_query_flag) {    /* Okay,  pick it up  */
  350.             objdes(tmp_str, i_ptr, TRUE);
  351.             (void)sprintf(out_val, "Pick up %s? ", tmp_str);
  352.             pickup = get_check(out_val);
  353.         }
  354.         /* Check to see if it will change the players speed. */
  355.         if (pickup && !inven_check_weight(i_ptr)) {
  356.             objdes(tmp_str, i_ptr, TRUE);
  357.             (void)sprintf(out_val,
  358.                   "Exceed your weight limit to pick up %s? ",
  359.                   tmp_str);
  360.             pickup = get_check(out_val);
  361.         }
  362.         /* Attempt to pick up an object.           */
  363.         if (pickup) {
  364.             locn = inven_carry(i_ptr);
  365.             objdes(tmp_str, &inventory[locn], TRUE);
  366.             (void)sprintf(out_val, "You have %s. (%c)", tmp_str, locn + 'a');
  367.             msg_print(out_val);
  368.             (void)delete_object(y, x);
  369.         }
  370.         } else if (pickup) {   /* only if was trying to pick it up...
  371.                     * -CFT */
  372.         objdes(tmp_str, i_ptr, TRUE);
  373.         (void)sprintf(out_val, "You can't carry %s.", tmp_str);
  374.         msg_print(out_val);
  375.         }
  376.     }
  377.     }
  378. /* OOPS!                   */
  379.     else if (i == TV_INVIS_TRAP || i == TV_VIS_TRAP || i == TV_STORE_DOOR)
  380.     hit_trap(y, x);
  381. }
  382.  
  383. void 
  384. check_unique(m_ptr)
  385.     monster_type       *m_ptr;
  386. {
  387.     if (c_list[m_ptr->mptr].cdefense & UNIQUE)
  388.     u_list[m_ptr->mptr].exist = 0;
  389. }
  390.  
  391.  
  392. void 
  393. delete_unique()
  394. {
  395.     int                 i;
  396.  
  397.     for (i = 0; i < MAX_CREATURES; i++)
  398.     if (c_list[i].cdefense & UNIQUE)
  399.         u_list[i].exist = 0;
  400. }
  401.  
  402. /* Deletes a monster entry from the level        -RAK-     */
  403. void 
  404. delete_monster(j)
  405.     int                 j;
  406. {
  407.     register monster_type *m_ptr;
  408.  
  409.     if (j < 2)
  410.     return;               /* trouble? abort! -CFT */
  411.     m_ptr = &m_list[j];
  412.     if (c_list[m_ptr->mptr].cdefense & UNIQUE)
  413.     check_unique(m_ptr);
  414.     cave[m_ptr->fy][m_ptr->fx].cptr = 0;
  415.     if (m_ptr->ml)
  416.     lite_spot((int)m_ptr->fy, (int)m_ptr->fx);
  417.     if (j != mfptr - 1) {
  418. #ifdef TARGET
  419.     /* This targetting code stolen from Morgul -CFT */
  420.     if (j==target_mon) target_mode = FALSE;   /* Targetted monster dead or
  421.                              compacted.      CDW */
  422.     if (target_mon==mfptr-1) target_mon = j;  /* Targetted monster moved
  423.                              to replace dead or
  424.                              compacted monster   CDW */
  425. #endif
  426.     m_ptr = &m_list[mfptr - 1];
  427.     cave[m_ptr->fy][m_ptr->fx].cptr = j;
  428.     m_list[j] = m_list[mfptr - 1];
  429.     }
  430.     mfptr--;
  431.     m_list[mfptr] = blank_monster;
  432.     if (mon_tot_mult > 0)
  433.     mon_tot_mult--;
  434. }
  435.  
  436. /*
  437.  * The following two procedures implement the same function as delete
  438.  * monster. However, they are used within creatures(), because deleting a
  439.  * monster while scanning the m_list causes two problems, monsters might get
  440.  * two turns, and m_ptr/monptr might be invalid after the delete_monster.
  441.  * Hence the delete is done in two steps. 
  442.  */
  443. /*
  444.  * fix1_delete_monster does everything delete_monster does except delete the
  445.  * monster record and reduce mfptr, this is called in breathe, and a couple
  446.  * of places in creatures.c 
  447.  */
  448. void 
  449. fix1_delete_monster(j)
  450.     int                 j;
  451. {
  452.     register monster_type *m_ptr;
  453.  
  454.     if (j < 2)
  455.     return;               /* trouble? abort! -CFT */
  456. #ifdef TARGET
  457.     /* This targetting code stolen from Morgul -CFT */
  458.     if (j==target_mon) target_mode = FALSE;   /* Targetted monster dead or
  459.                          compacted.      CDW */
  460.     if (target_mon==mfptr-1) target_mon = j;  /* Targetted monster moved
  461.                          to replace dead or
  462.                          compacted monster   CDW */
  463. #endif
  464.     m_ptr = &m_list[j];
  465.     if (c_list[m_ptr->mptr].cdefense & UNIQUE)
  466.     check_unique(m_ptr);
  467. /*
  468.  * force the hp negative to ensure that the monster is dead, for example, if
  469.  * the monster was just eaten by another, it will still have positive hit
  470.  * points 
  471.  */
  472.     m_ptr->hp = (-1);
  473.     cave[m_ptr->fy][m_ptr->fx].cptr = 0;
  474.     if (m_ptr->ml)
  475.     lite_spot((int)m_ptr->fy, (int)m_ptr->fx);
  476.     if (mon_tot_mult > 0)
  477.     mon_tot_mult--;
  478. }
  479.  
  480. /*
  481.  * fix2_delete_monster does everything in delete_monster that wasn't done by
  482.  * fix1_monster_delete above, this is only called in creatures() 
  483.  */
  484. void 
  485. fix2_delete_monster(j)
  486.     int                 j;
  487. {
  488.     register monster_type *m_ptr;
  489.  
  490.     if (j < 2)
  491.     return;               /* trouble? abort! -CFT */
  492.     m_ptr = &m_list[j];           /* Fixed from a c_list ptr to a m_list
  493.                     * ptr. -CFT */
  494.     if (c_list[m_ptr->mptr].cdefense & UNIQUE)
  495.     check_unique(m_ptr);
  496.     if (j != mfptr - 1) {
  497.     m_ptr = &m_list[mfptr - 1];
  498.     cave[m_ptr->fy][m_ptr->fx].cptr = j;
  499.     m_list[j] = m_list[mfptr - 1];
  500.     }
  501.     m_list[mfptr - 1] = blank_monster;
  502.     mfptr--;
  503. }
  504.  
  505.  
  506. /* Creates objects nearby the coordinates given        -RAK-      */
  507. static int 
  508. summon_object(y, x, num, typ, good)
  509.     int                 y, x, num, typ;
  510.     int32u              good;
  511. {
  512.     register int        i, j, k;
  513.     register cave_type *c_ptr;
  514.     int                 real_typ, res;
  515.  
  516.     if (typ == 1)
  517.     real_typ = 1;           /* typ == 1 -> objects */
  518.     else
  519.     real_typ = 256;           /* typ == 2 -> gold */
  520.     res = 0;
  521.     do {
  522.     i = 0;
  523.     do {
  524.         j = y - 3 + randint(5);
  525.         k = x - 3 + randint(5);
  526.         if (in_bounds(j, k) && los(y, x, j, k)) {
  527.         c_ptr = &cave[j][k];
  528.         if (c_ptr->fval <= MAX_OPEN_SPACE && (c_ptr->tptr == 0)) {
  529.             if (typ == 3) {/* typ == 3 -> 50% objects, 50% gold */
  530.             if (randint(100) < 50)
  531.                 real_typ = 1;
  532.             else
  533.                 real_typ = 256;
  534.             }
  535.             if (real_typ == 1) {
  536.             if (good)
  537.                 place_special(j, k, good);
  538.             else
  539.                 place_object(j, k);
  540.             } else {
  541.             if (good)
  542.                 place_special(j, k, good);
  543.             else
  544.                 place_gold(j, k);
  545.             }
  546.             lite_spot(j, k);
  547.             if (test_light(j, k))
  548.             res += real_typ;
  549.             i = 20;
  550.         }
  551.         }
  552.         i++;
  553.     }
  554.     while (i <= 20);
  555.     num--;
  556.     }
  557.     while (num != 0);
  558.     return res;
  559. }
  560.  
  561.  
  562. /* Deletes object from given location            -RAK-     */
  563. int 
  564. delete_object(y, x)
  565.     int                 y, x;
  566. {
  567.     register int        delete;
  568.     register cave_type *c_ptr;
  569.  
  570.     c_ptr = &cave[y][x];
  571.     if (c_ptr->fval == BLOCKED_FLOOR)
  572.     c_ptr->fval = CORR_FLOOR;
  573.     pusht(c_ptr->tptr);           /* then eliminate it */
  574.     c_ptr->tptr = 0;
  575.     c_ptr->fm = FALSE;
  576.     lite_spot(y, x);
  577.     if (test_light(y, x))
  578.     delete = TRUE;
  579.     else
  580.     delete = FALSE;
  581.     return (delete);
  582. }
  583.  
  584.  
  585. /* Allocates objects upon a creatures death        -RAK-     */
  586. /* Oh well,  another creature bites the dust.  Reward the victor */
  587. /* based on flags set in the main creature record         */
  588. /*
  589.  * Returns a mask of bits from the given flags which indicates what the
  590.  * monster is seen to have dropped.  This may be added to monster memory. 
  591.  */
  592. int32u 
  593. monster_death(y, x, flags, good, win)
  594.     int                 y, x;
  595.     register int32u     flags;
  596.     int32u              good;
  597.     int32u              win;
  598. {
  599.     register int        i, number;
  600.     int32u              dump, res;
  601.  
  602. #if defined(ATARIST_MWC)
  603.     int32u              holder;       /* avoid a compiler bug */
  604. #endif
  605.  
  606.     if (win & CM_WIN) {           /* MORGOTH */
  607.     register int        j, k;
  608.     register cave_type *c_ptr;
  609.     int                 crown = FALSE, grond = FALSE;
  610.  
  611.     i = 0;
  612.     do {
  613.         j = y - 3 + randint(5);
  614.         k = x - 3 + randint(5);
  615.         if (in_bounds(j, k) && los(y, x, j, k)) {
  616.         c_ptr = &cave[j][k];
  617.         if (c_ptr->fval <= MAX_OPEN_SPACE && (c_ptr->tptr == 0)) {
  618.             if (!crown) {
  619.             int                 cur_pos;
  620.             inven_type         *t_ptr;
  621.  
  622.             crown = TRUE;
  623.             cur_pos = popt();
  624.             cave[j][k].tptr = cur_pos;
  625.             invcopy(&t_list[cur_pos], 98);
  626.             t_ptr = &t_list[cur_pos];
  627.             t_ptr->flags |= (TR_STR | TR_DEX | TR_CON | TR_INT | TR_WIS | TR_CHR |
  628.                        TR_SEE_INVIS | TR_CURSED | TR_INFRA);
  629.             t_ptr->flags2 |= (TR_TELEPATHY | TR_LIGHT | TR_ARTIFACT);
  630.             t_ptr->ident |= ID_NOSHOW_TYPE;
  631.             t_ptr->name2 = SN_MORGOTH;
  632.             t_ptr->p1 = 125;
  633.             t_ptr->cost = 10000000L;
  634.             if (cave[j][k].cptr == 1)
  635.                 msg_print("You feel something roll beneath your feet.");
  636.             } else {
  637.             int                 cur_pos;
  638.             inven_type         *t_ptr;
  639.  
  640.             grond = TRUE;
  641.             cur_pos = popt();
  642.             cave[j][k].tptr = cur_pos;
  643.             invcopy(&t_list[cur_pos], 56);
  644.             t_ptr = &t_list[cur_pos];
  645.             t_ptr->name2 = SN_GROND;
  646.             t_ptr->tohit = 5;
  647.             t_ptr->todam = 25;
  648.             t_ptr->damage[0] = 10;
  649.             t_ptr->damage[1] = 8;
  650.             t_ptr->weight = 600;
  651.             t_ptr->flags = (TR_SEE_INVIS | TR_SLAY_EVIL | TR_SLAY_UNDEAD |
  652.                     TR_RES_FIRE | TR_RES_COLD | TR_RES_LIGHT | TR_RES_ACID |
  653.                     TR_SLAY_ANIMAL | TR_SPEED | TR_SLAY_X_DRAGON | TR_AGGRAVATE);
  654.             t_ptr->flags2 = (TR_SLAY_DEMON | TR_SLAY_TROLL | TR_SLAY_ORC |
  655.                     TR_IMPACT | TR_TELEPATHY | TR_ARTIFACT);
  656.             t_ptr->p1 = (-1);
  657.             t_ptr->toac = 10;
  658.             t_ptr->cost = 500000L;
  659.             t_ptr->ident |= ID_SHOW_HITDAM;
  660.             GROND = 1;
  661.             if (cave[j][k].cptr == 1)
  662.                 msg_print("You feel something roll beneath your feet.");
  663.             }
  664.             lite_spot(j, k);
  665.         }
  666.         }
  667.         i++;
  668.     }
  669.     while (!grond && i < 50);
  670.     }
  671. #if !defined(ATARIST_MWC)
  672.     if (flags & CM_CARRY_OBJ)
  673.     i = 1;
  674.     else
  675.     i = 0;
  676.     if (flags & CM_CARRY_GOLD)
  677.     i += 2;
  678.  
  679.     number = 0;
  680.     if ((flags & CM_60_RANDOM) && (randint(100) < 60))
  681.     number++;
  682.     if ((flags & CM_90_RANDOM) && (randint(100) < 90))
  683.     number++;
  684.     if (flags & CM_1D2_OBJ)
  685.     number += randint(2);
  686.     if (flags & CM_2D2_OBJ)
  687.     number += damroll(2, 2);
  688.     if (flags & CM_4D2_OBJ)
  689.     number += damroll(4, 2);
  690.     if (number > 0)
  691.     dump = summon_object(y, x, number, i, good);
  692.     else
  693.     dump = 0;
  694. #else
  695.     holder = CM_CARRY_OBJ;
  696.     if (flags & holder)
  697.     i = 1;
  698.     else
  699.     i = 0;
  700.     holder = CM_CARRY_GOLD;
  701.     if (flags & holder)
  702.     i += 2;
  703.  
  704.     number = 0;
  705.     holder = CM_60_RANDOM;
  706.     if ((flags & holder) && (randint(100) < 60))
  707.     number++;
  708.     holder = CM_90_RANDOM;
  709.     if ((flags & holder) && (randint(100) < 90))
  710.     number++;
  711.     holder = CM_1D2_OBJ;
  712.     if (flags & holder)
  713.     number += randint(2);
  714.     holder = CM_2D2_OBJ;
  715.     if (flags & holder)
  716.     number += damroll(2, 2);
  717.     holder = CM_4D2_OBJ;
  718.     if (flags & holder)
  719.     number += damroll(4, 2);
  720.     if (number > 0)
  721.     dump = summon_object(y, x, number, i, good);
  722.     else
  723.     dump = 0;
  724.  
  725.  
  726. #endif
  727.  
  728. #if defined(ATARIST_MWC)
  729.     holder = CM_WIN;
  730.     if (flags & holder)
  731. #else
  732.     if (flags & CM_WIN)
  733. #endif
  734.     {
  735.     total_winner = TRUE;
  736.     prt_winner();
  737.     msg_print("*** CONGRATULATIONS *** You have won the game.");
  738.     msg_print("You cannot save this game, but you may retire when ready.");
  739.     }
  740.     if (dump) {
  741.     res = 0;
  742.     if (dump & 255)
  743. #ifdef ATARIST_MWC
  744.     {
  745.         holder = CM_CARRY_OBJ;
  746.         res |= holder;
  747.     }
  748. #else
  749.         res |= CM_CARRY_OBJ;
  750. #endif
  751.     if (dump >= 256)
  752. #ifdef ATARIST_MWC
  753.     {
  754.         holder = CM_CARRY_GOLD;
  755.         res |= holder;
  756.     }
  757. #else
  758.         res |= CM_CARRY_GOLD;
  759. #endif
  760.     dump = (dump % 256) + (dump / 256);    /* number of items */
  761.     res |= dump << CM_TR_SHIFT;
  762.     } else
  763.     res = 0;
  764.  
  765.     return res;
  766. }
  767.  
  768. /* return whether a monster is "fearless" and will never run away. -CWS */
  769.  
  770. static int 
  771. fearless(c_ptr)
  772.     creature_type      *c_ptr;
  773. {
  774.     int                 flag = FALSE;
  775.  
  776.     if (c_ptr->cdefense & MINDLESS)
  777.     flag = TRUE;
  778.  
  779.     if (c_ptr->cdefense & UNDEAD) {
  780.     if (c_ptr->spells ||       /* if undead, check to see if it's */
  781.         c_ptr->spells2 ||       /* "mindless", ie has no spells */
  782.         c_ptr->spells3)
  783.         flag = FALSE;       /* found a spell, so not mindless   */
  784.     else
  785.         flag = TRUE;       /* "mindless" undead */
  786.     }
  787.  
  788.     if (c_ptr->cchar == 'E' || c_ptr->cchar == 'g' || c_ptr->cdefense & DEMON)
  789.     flag = TRUE;
  790.  
  791.     if (c_ptr->cdefense & INTELLIGENT)    /* catch intelligent monsters */
  792.     flag = FALSE;
  793.  
  794.     if (!(c_ptr->cmove & CM_MOVE_NORMAL))    /* it can't run away */
  795.     flag = TRUE;
  796.  
  797.     return (flag);
  798. }
  799.  
  800.  
  801. /* Decreases monsters hit points and deletes monster if needed.     */
  802. /* (Picking on my babies.)                   -RAK-   */
  803. /* added fear (DGK) and check whether to print fear messages -CWS */
  804. int 
  805. mon_take_hit(monptr, dam, print_fear)
  806.     int                 monptr, dam, print_fear;
  807. {
  808.     register int32u     i;
  809.     int                 found = FALSE;
  810.     int32               new_exp, new_exp_frac;
  811.     register monster_type *m_ptr;
  812.     register struct misc *p_ptr;
  813.     register creature_type *c_ptr;
  814.     int                 m_take_hit = (-1);
  815.     int32u              tmp;
  816.     int                 percentage;
  817.     char                m_name[80];
  818.     vtype               out_val;
  819.  
  820.     m_ptr = &m_list[monptr];
  821.     m_ptr->hp -= dam;
  822.     m_ptr->csleep = 0;
  823.     c_ptr = &c_list[m_ptr->mptr];
  824.  
  825.     if (m_ptr->hp < 0) {
  826.     if (m_ptr->mptr == (MAX_CREATURES - 1)) {
  827.         char                temp[100];
  828.  
  829.         if (!dun_level) {
  830.         sprintf(temp, "%s/%d", ANGBAND_BONES, c_list[m_ptr->mptr].level);
  831.         } else {
  832.         sprintf(temp, "%s/%d", ANGBAND_BONES, dun_level);
  833.         }
  834.         unlink(temp);
  835.     }
  836.     if (c_list[m_ptr->mptr].cdefense & QUESTOR) {
  837.         for (i = 0; i < DEFINED_QUESTS; i++) {    /* search for monster's
  838.                              * lv, not... */
  839.         if (quests[i] == c_list[m_ptr->mptr].level) {    /* ...cur lv. -CFT */
  840.             quests[i] = 0;
  841.             found = TRUE;
  842.             break;
  843.         }
  844.         }
  845.         if (found) {
  846.         if ((unsigned) dun_level != c_list[m_ptr->mptr].level) {
  847.             /* just mesg */
  848.             msg_print("Well done!!  Now continue onward towards Morgoth.");
  849.         } else {       /* stairs and mesg */
  850.             cave_type          *ca_ptr;
  851.             int                 cur_pos;
  852.  
  853.             ca_ptr = &cave[m_ptr->fy][m_ptr->fx];
  854.             if (ca_ptr->tptr != 0) {    /* don't overwrite artifact
  855.                          * -CFT */
  856.             int                 ty = m_ptr->fy, tx = m_ptr->fx, ny, nx;
  857.  
  858.             while ((cave[ty][tx].tptr != 0) &&
  859.               (t_list[cave[ty][tx].tptr].tval >= TV_MIN_WEAR) &&
  860.               (t_list[cave[ty][tx].tptr].tval <= TV_MAX_WEAR) &&
  861.              (t_list[cave[ty][tx].tptr].flags2 & TR_ARTIFACT)) {
  862.                 do { /* pick new possible spot */
  863.                 ny = ty + (int8u) randint(3) - 2;
  864.                 nx = tx + (int8u) randint(3) - 2;
  865.                 } while (!in_bounds(ny, nx) ||
  866.                      (cave[ny][nx].fval > MAX_OPEN_SPACE));
  867.                 ty = ny;    /* this is a new spot, not in a
  868.                      * wall/door/etc */
  869.                 tx = nx;
  870.             } /* ok, to exit this, [ty][tx] must not be artifact
  871.                * -CFT */
  872.             if (cave[ty][tx].tptr != 0)    /* so we can delete it
  873.                              * -CFT */
  874.                 (void)delete_object(ty, tx);
  875.             ca_ptr = &cave[ty][tx];    /* put stairway here... */
  876.             }
  877.             cur_pos = popt();
  878.             ca_ptr->tptr = cur_pos;
  879.             invcopy(&t_list[cur_pos], OBJ_DOWN_STAIR);
  880.             msg_print("Well done!! Go for it!");
  881.             msg_print("A magical stairway appears...");
  882.         } /* if-else for stairway */
  883.         } /* if found */
  884.     } /* if quest monster */
  885.     object_level = (dun_level + c_ptr->level) >> 1;
  886.     i = monster_death((int)m_ptr->fy, (int)m_ptr->fx,
  887.               c_list[m_ptr->mptr].cmove,
  888.               (c_list[m_ptr->mptr].cdefense & (SPECIAL | GOOD)),
  889.               (c_list[m_ptr->mptr].cmove & WINNER));
  890.     if ((py.flags.blind < 1 && m_ptr->ml) ||
  891.         (c_list[m_ptr->mptr].cmove & CM_WIN) ||
  892.         (c_list[m_ptr->mptr].cdefense & UNIQUE)) { /* recall even invisible uniques */
  893.         tmp = (c_recall[m_ptr->mptr].r_cmove & CM_TREASURE) >> CM_TR_SHIFT;
  894.         if (tmp > ((i & CM_TREASURE) >> CM_TR_SHIFT))
  895.         i = (i & ~CM_TREASURE) | (tmp << CM_TR_SHIFT);
  896.         c_recall[m_ptr->mptr].r_cmove =
  897.         (c_recall[m_ptr->mptr].r_cmove & ~CM_TREASURE) | i;
  898.         if (c_recall[m_ptr->mptr].r_kills < MAX_SHORT)
  899.         c_recall[m_ptr->mptr].r_kills++;
  900.     }
  901.     c_ptr = &c_list[m_ptr->mptr];
  902.     p_ptr = &py.misc;
  903.  
  904.     if (c_ptr->cdefense & UNIQUE) {
  905.         u_list[m_ptr->mptr].exist = 0;
  906.         u_list[m_ptr->mptr].dead = 1;
  907.     }
  908.     new_exp = ((long)c_ptr->mexp * c_ptr->level) / p_ptr->lev;
  909.     new_exp_frac = ((((long)c_ptr->mexp * c_ptr->level) % p_ptr->lev)
  910.             * 0x10000L / p_ptr->lev) + p_ptr->exp_frac;
  911.     if (new_exp_frac >= 0x10000L) {
  912.         new_exp++;
  913.         p_ptr->exp_frac = new_exp_frac - 0x10000L;
  914.     } else
  915.         p_ptr->exp_frac = new_exp_frac;
  916.  
  917.     p_ptr->exp += new_exp;
  918.     /*
  919.      * can't call prt_experience() here, as that would result in "new level"
  920.      * message appearing before "monster dies" message 
  921.      */
  922.     m_take_hit = m_ptr->mptr;
  923.     /*
  924.      * in case this is called from within creatures(), this is a horrible
  925.      * hack, the m_list/creatures() code needs to be rewritten 
  926.      */
  927.     if (hack_monptr < monptr)
  928.         delete_monster(monptr);
  929.     else
  930.         fix1_delete_monster(monptr);
  931.     monster_is_afraid = 0;
  932.     } else {
  933.     if (m_ptr->maxhp <= 0)       /* Then fix it! -DGK */
  934.         m_ptr->maxhp = 1;
  935.     percentage = (m_ptr->hp * 100L) / (m_ptr->maxhp);
  936.  
  937.     if (fearless(c_ptr)) {
  938.         monster_is_afraid = 0;
  939.         return (-1);
  940.     }
  941.     if (!(m_ptr->monfear) &&
  942.         ((percentage <= 10 && randint(10) <= percentage) || (dam >= m_ptr->hp)))
  943.     /*
  944.      * Run if at 10% or less of max hit points, or got hit for half its
  945.      * current hit points -DGK 
  946.      */
  947.     {
  948.         monster_is_afraid = 1;
  949.         if (print_fear && m_ptr->ml &&
  950.         los(char_row, char_col, m_ptr->fy, m_ptr->fx)) {
  951.         monster_name(m_name, m_ptr, c_ptr);
  952.         sprintf(out_val, "%s flees in terror!", m_name);
  953.         msg_print(out_val);
  954.         }
  955.         m_ptr->monfear = randint(10) + ((dam >= m_ptr->hp && percentage > 7) ?
  956.                         20 : (11 - percentage) * 5);
  957.     } else if (m_ptr->monfear) {
  958.         m_ptr->monfear -= randint(dam);
  959.         if (m_ptr->monfear <= 0) {
  960.         if (monster_is_afraid == 1)
  961.             monster_is_afraid = (-1);
  962.         m_ptr->monfear = 0;
  963.         if (m_ptr->ml && print_fear) {
  964.             char                sex = c_ptr->gender;
  965.  
  966.             monster_name(m_name, m_ptr, c_ptr);
  967.             sprintf(out_val, "%s recovers %s courage.", m_name,
  968.                 (sex == 'm' ? "his" : sex == 'f' ? "her" :
  969.                  sex == 'p' ? "their" : "its"));
  970.             msg_print(out_val);
  971.         }
  972.         }
  973.     }
  974.     m_take_hit = (-1);
  975.     }
  976.     return (m_take_hit);
  977. }
  978.  
  979.  
  980. /* Player attacks a (poor, defenseless) creature    -RAK-     */
  981. static void 
  982. py_attack(y, x)
  983.     int                 y, x;
  984. {
  985.     register int        k, blows;
  986.     int                 crptr, monptr, tot_tohit, base_tohit;
  987.     vtype               m_name, out_val;
  988.     register inven_type *i_ptr;
  989.     register struct misc *p_ptr;
  990.  
  991.     crptr = cave[y][x].cptr;
  992.     monptr = m_list[crptr].mptr;
  993.     m_list[crptr].csleep = 0;
  994.     i_ptr = &inventory[INVEN_WIELD];
  995. /* Does the player know what he's fighting?       */
  996.     if (!m_list[crptr].ml)
  997.     (void)strcpy(m_name, "it");
  998.     else {
  999.     if (c_list[monptr].cdefense & UNIQUE)
  1000.         (void)sprintf(m_name, "%s", c_list[monptr].name);
  1001.     else
  1002.         (void)sprintf(m_name, "the %s", c_list[monptr].name);
  1003.     }
  1004.     if (i_ptr->tval != TV_NOTHING) /* Proper weapon */
  1005.     blows = attack_blows((int)i_ptr->weight, &tot_tohit);
  1006.     else {               /* Bare hands?   */
  1007.     blows = 2;
  1008.     tot_tohit = (-3);
  1009.     }
  1010.     if ((i_ptr->tval >= TV_SLING_AMMO) && (i_ptr->tval <= TV_ARROW))
  1011.     /* Fix for arrows */
  1012.     blows = 1;
  1013.     p_ptr = &py.misc;
  1014.     tot_tohit += p_ptr->ptohit;
  1015. /* if creature not lit, make it more difficult to hit */
  1016.     if (m_list[crptr].ml)
  1017.     base_tohit = p_ptr->bth;
  1018.     else
  1019.     base_tohit = (p_ptr->bth / 2) - (tot_tohit * (BTH_PLUS_ADJ - 1))
  1020.         - (p_ptr->lev * class_level_adj[p_ptr->pclass][CLA_BTH] / 2);
  1021.  
  1022. /* Loop for number of blows,    trying to hit the critter.      */
  1023.     monster_is_afraid = 0;       /* redo fear messages -CWS        */
  1024.     do {
  1025.     if (test_hit(base_tohit, (int)p_ptr->lev, tot_tohit,
  1026.              (int)c_list[monptr].ac, CLA_BTH)) {
  1027.  
  1028.         if (!wizard) {
  1029.         (void) sprintf(out_val, "You hit %s.", m_name);
  1030.         msg_print(out_val);
  1031.         }
  1032.  
  1033.         if (i_ptr->tval != TV_NOTHING) {
  1034.         k = pdamroll(i_ptr->damage);
  1035.         k = tot_dam(i_ptr, k, monptr);
  1036.         k = critical_blow((int)i_ptr->weight, tot_tohit, k, CLA_BTH);
  1037.         } else {           /* Bare hands!?  */
  1038.         k = damroll(1, 1);
  1039.         k = critical_blow(1, 0, k, CLA_BTH);
  1040.         }
  1041.         k += p_ptr->ptodam;
  1042.  
  1043.         if (wizard) {
  1044.         (void)sprintf(out_val,
  1045.                   "You hit %s with %d hp, doing %d+%d damage.",
  1046.                   m_name, m_list[crptr].hp, (k - p_ptr->ptodam),
  1047.                   p_ptr->ptodam);
  1048.         msg_print(out_val);
  1049.         }
  1050.  
  1051.         if (k < 0)
  1052.         k = 0;
  1053.  
  1054.         if (py.flags.confuse_monster) {
  1055.         py.flags.confuse_monster = FALSE;
  1056.         msg_print("Your hands stop glowing.");
  1057.         if ((c_list[monptr].cdefense & CHARM_SLEEP)
  1058.             || (randint(MAX_MONS_LEVEL) < c_list[monptr].level))
  1059.             (void)sprintf(out_val, "%s is unaffected.", m_name);
  1060.         else {
  1061.             (void)sprintf(out_val, "%s appears confused.", m_name);
  1062.             m_list[crptr].confused = TRUE;
  1063.         }
  1064.         if ((out_val[0] >= 'a') && (out_val[0] <= 'z'))
  1065.             out_val[0] -= 32;    /* upcase, because starts sentence
  1066.                      * -CFT */
  1067.         msg_print(out_val);
  1068.         if (m_list[crptr].ml && randint(4) == 1)
  1069.             c_recall[monptr].r_cdefense |=
  1070.             c_list[monptr].cdefense & CHARM_SLEEP;
  1071.         }
  1072.         if (k < 0)
  1073.         k = 0;           /* no neg damage! */
  1074.  
  1075.     /* See if we done it in.                 */
  1076.         if (mon_take_hit(crptr, k, FALSE) >= 0) {    /* never print msgs -CWS */
  1077.         if ((c_list[monptr].cdefense & (DEMON|UNDEAD|MINDLESS)) ||
  1078.             (c_list[monptr].cchar == 'E') ||
  1079.             (c_list[monptr].cchar == 'v') ||
  1080.             (c_list[monptr].cchar == 'g'))
  1081.             (void)sprintf(out_val, "You have destroyed %s.", m_name);
  1082.         else
  1083.             (void)sprintf(out_val, "You have slain %s.", m_name);
  1084.         msg_print(out_val);
  1085.         prt_experience();
  1086.         blows = 0;
  1087.         }
  1088.         if ((i_ptr->tval >= TV_SLING_AMMO)
  1089.         && (i_ptr->tval <= TV_ARROW)) {    /* Use missiles up */
  1090.         i_ptr->number--;
  1091.         inven_weight -= i_ptr->weight;
  1092.         py.flags.status |= PY_STR_WGT;
  1093.         if (i_ptr->number == 0) {
  1094.             equip_ctr--;
  1095.             py_bonuses(i_ptr, -1);
  1096.             invcopy(i_ptr, OBJ_NOTHING);
  1097.             calc_bonuses();
  1098.         }
  1099.         }
  1100.     } else {
  1101.         (void)sprintf(out_val, "You miss %s.", m_name);
  1102.         msg_print(out_val);
  1103.     }
  1104.     blows--;
  1105.     }
  1106.     while (blows >= 1);
  1107.  
  1108. /* redo fear messages to only print at the end -CWS */
  1109.     if (monster_is_afraid == 1) {
  1110.     sprintf(out_val, "%s flees in terror!", m_name);
  1111.     msg_print(out_val);
  1112.     }
  1113.     if (monster_is_afraid == -1) {
  1114.     char                sex = c_list[monptr].gender;
  1115.  
  1116.     sprintf(out_val, "%s recovers %s courage.", m_name,
  1117.         (sex == 'm' ? "his" : sex == 'f' ? "her" :
  1118.          sex == 'p' ? "their" : "its"));
  1119.     msg_print(out_val);
  1120.     }
  1121. }
  1122.  
  1123.  
  1124. /* Moves player from one space to another.        -RAK-     */
  1125. /* Note: This routine has been pre-declared; see that for argument */
  1126. void 
  1127. move_char(dir, do_pickup)
  1128.     int                 dir, do_pickup;
  1129. {
  1130.     int                 old_row, old_col, old_find_flag;
  1131.     int                 y, x;
  1132.     register int        i, j;
  1133.     register cave_type *c_ptr, *d_ptr;
  1134.  
  1135.     if (((py.flags.confused > 0) || (py.flags.stun > 0)) &&    /* Confused/Stunned?  */
  1136.     (randint(4) > 1) &&       /* 75% random movement */
  1137.     (dir != 5)) {           /* Never random if sitting */
  1138.     dir = randint(9);
  1139.     end_find();
  1140.     }
  1141.     y = char_row;
  1142.     x = char_col;
  1143.     if (mmove(dir, &y, &x)) {       /* Legal move?          */
  1144.     c_ptr = &cave[y][x];
  1145.     /* if there is no creature, or an unlit creature in the walls then... */
  1146.     /*
  1147.      * disallow attacks against unlit creatures in walls because moving into
  1148.      * a wall is a free turn normally, hence don't give player free turns
  1149.      * attacking each wall in an attempt to locate the invisible creature,
  1150.      * instead force player to tunnel into walls which always takes a turn 
  1151.      */
  1152.     if ((c_ptr->cptr < 2)
  1153.       || (!m_list[c_ptr->cptr].ml && c_ptr->fval >= MIN_CLOSED_SPACE)) {
  1154.         if (c_ptr->fval <= MAX_OPEN_SPACE) {    /* Open floor spot     */
  1155.         /* Make final assignments of char co-ords */
  1156.         old_row = char_row;
  1157.         old_col = char_col;
  1158.         char_row = y;
  1159.         char_col = x;
  1160.         /* Move character record (-1)           */
  1161.         move_rec(old_row, old_col, char_row, char_col);
  1162.         /* Check for new panel               */
  1163.         if (get_panel(char_row, char_col, FALSE))
  1164.             prt_map();
  1165.         /* Check to see if he should stop           */
  1166.         if (find_flag)
  1167.             area_affect(dir, char_row, char_col);
  1168.         /* Check to see if he notices something  */
  1169.         /* fos may be negative if have good rings of searching */
  1170.         if ((py.misc.fos <= 1) || (randint(py.misc.fos) == 1) ||
  1171.             (py.flags.status & PY_SEARCH))
  1172.             search(char_row, char_col, py.misc.srh);
  1173.         /* A room of light should be lit.         */
  1174.         if ((c_ptr->fval == LIGHT_FLOOR) ||
  1175.             (c_ptr->fval == NT_LIGHT_FLOOR)) {
  1176.             if (!c_ptr->pl && !py.flags.blind)
  1177.             light_room(char_row, char_col);
  1178.         }
  1179.         /* In doorway of light-room?           */
  1180.         else if (c_ptr->lr && (py.flags.blind < 1)) {
  1181.             int8u               lit = FALSE;    /* only call light_room
  1182.                              * once... -CFT */
  1183.  
  1184.             for (i = (char_row - 1); !lit && i <= (char_row + 1); i++)
  1185.             for (j = (char_col - 1); !lit && j <= (char_col + 1); j++) {
  1186.                 d_ptr = &cave[i][j];
  1187.                 if (((d_ptr->fval == LIGHT_FLOOR) ||
  1188.                  (d_ptr->fval == NT_LIGHT_FLOOR)) &&
  1189.                 (!d_ptr->pl)) {
  1190.                 /* move light 1st, or corridor may be perm lit */
  1191.                 move_light(old_row, old_col, char_row, char_col);
  1192.                 light_room(char_row, char_col);
  1193.                 lit = TRUE;    /* okay, we can stop now...
  1194.                          * -CFT */
  1195.                 }
  1196.             }
  1197.         }
  1198.         /* Move the light source               */
  1199.         move_light(old_row, old_col, char_row, char_col);
  1200.         /* An object is beneath him.         */
  1201.         if (c_ptr->tptr != 0) {
  1202.             i = t_list[c_ptr->tptr].tval;
  1203.             if (i == TV_INVIS_TRAP || i == TV_VIS_TRAP
  1204.             || i == TV_STORE_DOOR || !prompt_carry_flag
  1205.             || i == TV_GOLD)
  1206.             carry(char_row, char_col, do_pickup);
  1207.             else if (prompt_carry_flag && i != TV_OPEN_DOOR
  1208.                  && i != TV_UP_STAIR && i != TV_DOWN_STAIR) {
  1209.             inven_type         *i_ptr;
  1210.             bigvtype            tmp_str, tmp2_str;
  1211.  
  1212.             i_ptr = &t_list[cave[char_row][char_col].tptr];
  1213.             objdes(tmp_str, i_ptr, TRUE);
  1214.             sprintf(tmp2_str, "You see %s.", tmp_str);
  1215.             msg_print(tmp2_str);
  1216.             }
  1217.         /*
  1218.          * if stepped on falling rock trap, and space contains
  1219.          * rubble, then step back into a clear area 
  1220.          */
  1221.             if (t_list[c_ptr->tptr].tval == TV_RUBBLE) {
  1222.             move_rec(char_row, char_col, old_row, old_col);
  1223.             move_light(char_row, char_col, old_row, old_col);
  1224.             char_row = old_row;
  1225.             char_col = old_col;
  1226.             /*
  1227.              * check to see if we have stepped back onto another
  1228.              * trap, if so, set it off 
  1229.              */
  1230.             c_ptr = &cave[char_row][char_col];
  1231.             if (c_ptr->tptr != 0) {
  1232.                 i = t_list[c_ptr->tptr].tval;
  1233.                 if (i == TV_INVIS_TRAP || i == TV_VIS_TRAP
  1234.                 || i == TV_STORE_DOOR)
  1235.                 hit_trap(char_row, char_col);
  1236.             }
  1237.             }
  1238.         }
  1239.         } else {           /* Can't move onto floor space */
  1240.         if (!find_flag && (c_ptr->tptr != 0)) {
  1241.             if (t_list[c_ptr->tptr].tval == TV_RUBBLE)
  1242.             msg_print("There is rubble blocking your way.");
  1243.             else if (t_list[c_ptr->tptr].tval == TV_CLOSED_DOOR)
  1244.             msg_print("There is a closed door blocking your way.");
  1245.         } else
  1246.             end_find();
  1247.         free_turn_flag = TRUE;
  1248.         }
  1249.     } else {           /* Attacking a creature! */
  1250.         old_find_flag = find_flag;
  1251.         end_find();
  1252.     /* if player can see monster, and was in find mode, then nothing */
  1253.         if (m_list[c_ptr->cptr].ml && old_find_flag) {
  1254.         /* did not do anything this turn */
  1255.         free_turn_flag = TRUE;
  1256.         } else {
  1257.         if (py.flags.afraid < 1)    /* Coward?     */
  1258.             py_attack(y, x);
  1259.         else           /* Coward!     */
  1260.             msg_print("You are too afraid!");
  1261.         }
  1262.     }
  1263.     }
  1264. }
  1265.  
  1266.  
  1267. /* Chests have traps too.                -RAK-     */
  1268. /* Note: Chest traps are based on the FLAGS value         */
  1269. static void 
  1270. chest_trap(y, x)
  1271.     int                 y, x;
  1272. {
  1273.     register int        i;
  1274.     int                 j, k;
  1275.     register inven_type *t_ptr;
  1276.  
  1277.     t_ptr = &t_list[cave[y][x].tptr];
  1278.     if (CH_LOSE_STR & t_ptr->flags) {
  1279.     msg_print("A small needle has pricked you!");
  1280.     if (!py.flags.sustain_str) {
  1281.         (void)dec_stat(A_STR);
  1282.         take_hit(damroll(1, 4), "a poison needle");
  1283.         msg_print("You feel weakened!");
  1284.     } else
  1285.         msg_print("You are unaffected.");
  1286.     }
  1287.     if (CH_POISON & t_ptr->flags) {
  1288.     msg_print("A small needle has pricked you!");
  1289.     take_hit(damroll(1, 6), "a poison needle");
  1290.     if (!(py.flags.poison_resist || py.flags.resist_poison ||
  1291.           py.flags.poison_im))
  1292.         py.flags.poisoned += 10 + randint(20);
  1293.     }
  1294.     if (CH_PARALYSED & t_ptr->flags) {
  1295.     msg_print("A puff of yellow gas surrounds you!");
  1296.     if (py.flags.free_act)
  1297.         msg_print("You are unaffected.");
  1298.     else {
  1299.         msg_print("You choke and pass out.");
  1300.         py.flags.paralysis = 10 + randint(20);
  1301.     }
  1302.     }
  1303.     if (CH_SUMMON & t_ptr->flags) {
  1304.     for (i = 0; i < 3; i++) {
  1305.         j = y;
  1306.         k = x;
  1307.         (void)summon_monster(&j, &k, FALSE);
  1308.     }
  1309.     }
  1310.     if (CH_EXPLODE & t_ptr->flags) {
  1311.     msg_print("There is a sudden explosion!");
  1312.     (void)delete_object(y, x);
  1313.     take_hit(damroll(5, 8), "an exploding chest");
  1314.     }
  1315. }
  1316.  
  1317.  
  1318. /* Opens a closed door or closed chest.        -RAK-     */
  1319. void 
  1320. openobject()
  1321. {
  1322.     int                 y, x, i, dir;
  1323.     int                 flag, no_object;
  1324.     register cave_type *c_ptr;
  1325.     register inven_type *t_ptr;
  1326.     register struct misc *p_ptr;
  1327.     register monster_type *m_ptr;
  1328.     vtype               m_name, out_val;
  1329. #ifdef TARGET
  1330.     int temp = target_mode; /* targetting will screw up get_dir, so we save
  1331.                    target_mode, then turn it off -CFT */
  1332. #endif
  1333.  
  1334.     y = char_row;
  1335.     x = char_col;
  1336. #ifdef TARGET
  1337.     target_mode = FALSE;
  1338. #endif
  1339.     if (get_dir(NULL, &dir)) {
  1340.     (void)mmove(dir, &y, &x);
  1341.     c_ptr = &cave[y][x];
  1342.     no_object = FALSE;
  1343.     if (c_ptr->cptr > 1 && c_ptr->tptr != 0 &&
  1344.         (t_list[c_ptr->tptr].tval == TV_CLOSED_DOOR
  1345.          || t_list[c_ptr->tptr].tval == TV_CHEST)) {
  1346.         m_ptr = &m_list[c_ptr->cptr];
  1347.         if (m_ptr->ml) {
  1348.         if (c_list[m_ptr->mptr].cdefense & UNIQUE)
  1349.             (void)sprintf(m_name, "%s", c_list[m_ptr->mptr].name);
  1350.         else
  1351.             (void)sprintf(m_name, "The %s", c_list[m_ptr->mptr].name);
  1352.         } else
  1353.         (void)strcpy(m_name, "Something");
  1354.         (void)sprintf(out_val, "%s is in your way!", m_name);
  1355.         msg_print(out_val);
  1356.     } else if (c_ptr->tptr != 0)
  1357.     /* Closed door         */
  1358.         if (t_list[c_ptr->tptr].tval == TV_CLOSED_DOOR) {
  1359.         t_ptr = &t_list[c_ptr->tptr];
  1360.         if (t_ptr->p1 > 0) {
  1361.             p_ptr = &py.misc;
  1362.             i = p_ptr->disarm + 2 * todis_adj() + stat_adj(A_INT)
  1363.             + (class_level_adj[p_ptr->pclass][CLA_DISARM]
  1364.                * p_ptr->lev / 3);
  1365.             if (py.flags.confused > 0)
  1366.             msg_print("You are too confused to pick the lock.");
  1367.             else if ((i - t_ptr->p1) > randint(100)) {
  1368.             msg_print("You have picked the lock.");
  1369.             py.misc.exp++;
  1370.             prt_experience();
  1371.             t_ptr->p1 = 0;
  1372.             } else
  1373.             count_msg_print("You failed to pick the lock.");
  1374.         } else if (t_ptr->p1 < 0)    /* It's stuck      */
  1375.             msg_print("It appears to be stuck.");
  1376.         if (t_ptr->p1 == 0) {
  1377.             invcopy(&t_list[c_ptr->tptr], OBJ_OPEN_DOOR);
  1378.             c_ptr->fval = CORR_FLOOR;
  1379.             lite_spot(y, x);
  1380.             check_view();
  1381.             command_count = 0;
  1382.         }
  1383.         }
  1384.     /* Open a closed chest.             */
  1385.         else if (t_list[c_ptr->tptr].tval == TV_CHEST) {
  1386.         p_ptr = &py.misc;
  1387.         i = p_ptr->disarm + 2 * todis_adj() + stat_adj(A_INT)
  1388.             + (class_level_adj[p_ptr->pclass][CLA_DISARM] * p_ptr->lev / 3);
  1389.         t_ptr = &t_list[c_ptr->tptr];
  1390.         flag = FALSE;
  1391.         if (CH_LOCKED & t_ptr->flags)
  1392.             if (py.flags.confused > 0)
  1393.             msg_print("You are too confused to pick the lock.");
  1394.             else if ((i - (int)t_ptr->level) > randint(100)) {
  1395.             msg_print("You have picked the lock.");
  1396.             flag = TRUE;
  1397.             py.misc.exp += t_ptr->level;
  1398.             prt_experience();
  1399.             } else
  1400.             count_msg_print("You failed to pick the lock.");
  1401.         else
  1402.             flag = TRUE;
  1403.         if (flag) {
  1404.             t_ptr->flags &= ~CH_LOCKED;
  1405.             t_ptr->name2 = SN_EMPTY;
  1406.             known2(t_ptr);
  1407.             t_ptr->cost = 0;
  1408.         }
  1409.         flag = FALSE;
  1410.         /* Was chest still trapped?     (Snicker)   */
  1411.         if ((CH_LOCKED & t_ptr->flags) == 0) {
  1412.             chest_trap(y, x);
  1413.             if (c_ptr->tptr != 0)
  1414.             flag = TRUE;
  1415.         }
  1416.         /* Chest treasure is allocated as if a creature   */
  1417.         /* had been killed.                   */
  1418.         if (flag) {
  1419.         /*
  1420.          * clear the cursed chest/monster win flag, so that people
  1421.          * can not win by opening a cursed chest 
  1422.          */
  1423.             t_ptr->flags &= ~TR_CURSED;
  1424.  
  1425.         /* generate based on level chest was found on - dbd */
  1426.             object_level = t_ptr->p1;
  1427.  
  1428.             /* but let's not get too crazy with storebought chests -CWS */
  1429.             if (t_ptr->ident & ID_STOREBOUGHT) {
  1430.             if (object_level > 20)
  1431.                 object_level = 20;
  1432.             }
  1433.  
  1434.             if (object_level < 0) /* perform some sanity checking -CWS */
  1435.             object_level = 0;
  1436.             if (object_level > 101)
  1437.             object_level = 101;
  1438.  
  1439.             (void)monster_death(y, x, t_list[c_ptr->tptr].flags, 0, 0);
  1440.             t_list[c_ptr->tptr].flags = 0;
  1441.         }
  1442.         } else
  1443.         no_object = TRUE;
  1444.     else
  1445.         no_object = TRUE;
  1446.  
  1447.     if (no_object) {
  1448.         msg_print("I do not see anything you can open there.");
  1449.         free_turn_flag = TRUE;
  1450.     }
  1451.     }
  1452. #ifdef TARGET
  1453.     target_mode = temp;
  1454. #endif
  1455. }
  1456.  
  1457.  
  1458. /* Closes an open door.                -RAK-     */
  1459. void 
  1460. closeobject()
  1461. {
  1462.     int                 y, x, dir, no_object;
  1463.     vtype               out_val, m_name;
  1464.     register cave_type *c_ptr;
  1465.     register monster_type *m_ptr;
  1466. #ifdef TARGET
  1467.     int temp = target_mode; /* targetting will screw up get_dir, so we save
  1468.                    target_mode, then turn it off -CFT */
  1469. #endif
  1470.  
  1471.     y = char_row;
  1472.     x = char_col;
  1473. #ifdef TARGET
  1474.     target_mode = FALSE;
  1475. #endif
  1476.     if (get_dir(NULL, &dir)) {
  1477.     (void)mmove(dir, &y, &x);
  1478.     c_ptr = &cave[y][x];
  1479.     no_object = FALSE;
  1480.     if (c_ptr->tptr != 0)
  1481.         if (t_list[c_ptr->tptr].tval == TV_OPEN_DOOR)
  1482.         if (c_ptr->cptr == 0)
  1483.             if (t_list[c_ptr->tptr].p1 == 0) {
  1484.             invcopy(&t_list[c_ptr->tptr], OBJ_CLOSED_DOOR);
  1485.             c_ptr->fval = BLOCKED_FLOOR;
  1486.             lite_spot(y, x);
  1487.             } else
  1488.             msg_print("The door appears to be broken.");
  1489.         else {
  1490.             m_ptr = &m_list[c_ptr->cptr];
  1491.             if (m_ptr->ml) {
  1492.             if (c_list[m_ptr->mptr].cdefense & UNIQUE)
  1493.                 (void)sprintf(m_name, "%s", c_list[m_ptr->mptr].name);
  1494.             else
  1495.                 (void)sprintf(m_name, "The %s", c_list[m_ptr->mptr].name);
  1496.             } else
  1497.             (void)strcpy(m_name, "Something");
  1498.             (void)sprintf(out_val, "%s is in your way!", m_name);
  1499.             msg_print(out_val);
  1500.         }
  1501.         else
  1502.         no_object = TRUE;
  1503.     else
  1504.         no_object = TRUE;
  1505.  
  1506.     if (no_object) {
  1507.         msg_print("I do not see anything you can close there.");
  1508.         free_turn_flag = TRUE;
  1509.     }
  1510.     }
  1511. #ifdef TARGET
  1512.     target_mode = temp;
  1513. #endif
  1514. }
  1515.  
  1516.  
  1517. /* Tunneling through real wall: 10, 11, 12        -RAK-     */
  1518. /* Used by TUNNEL and WALL_TO_MUD                 */
  1519. int 
  1520. twall(y, x, t1, t2)
  1521.     int                 y, x, t1, t2;
  1522. {
  1523.     register int        i, j;
  1524.     register cave_type *c_ptr;
  1525.     int                 res, found;
  1526.  
  1527.     res = FALSE;
  1528.     if (t1 > t2) {
  1529.     c_ptr = &cave[y][x];
  1530.     if (c_ptr->lr) {
  1531.     /*
  1532.      * should become a room space, check to see whether it should be
  1533.      * LIGHT_FLOOR or DARK_FLOOR 
  1534.      */
  1535.         found = FALSE;
  1536.         for (i = y - 1; i <= y + 1; i++)
  1537.         for (j = x - 1; j <= x + 1; j++)
  1538.             if (cave[i][j].fval <= MAX_CAVE_ROOM) {
  1539.             c_ptr->fval = cave[i][j].fval;
  1540.             c_ptr->pl = cave[i][j].pl;
  1541.             found = TRUE;
  1542.             break;
  1543.             }
  1544.         if (!found) {
  1545.         c_ptr->fval = CORR_FLOOR;
  1546.         c_ptr->pl = FALSE;
  1547.         }
  1548.     } else {
  1549.     /* should become a corridor space */
  1550.         c_ptr->fval = CORR_FLOOR;
  1551.         c_ptr->pl = FALSE;
  1552.     }
  1553.     c_ptr->fm = FALSE;
  1554.     if (panel_contains(y, x))
  1555.         if ((c_ptr->tl || c_ptr->pl) && c_ptr->tptr != 0)
  1556.         msg_print("You have found something!");
  1557.     lite_spot(y, x);
  1558.     res = TRUE;
  1559.     }
  1560.     return (res);
  1561. }
  1562.  
  1563.  
  1564. /* Tunnels through rubble and walls            -RAK-     */
  1565. /* Must take into account: secret doors,  special tools          */
  1566. void 
  1567. tunnel(dir)
  1568.     int                 dir;
  1569. {
  1570.     register int        i, tabil;
  1571.     register cave_type *c_ptr;
  1572.     register inven_type *i_ptr;
  1573.     int                 y, x;
  1574.     monster_type       *m_ptr;
  1575.     vtype               out_val, m_name;
  1576.  
  1577.     if ((py.flags.confused > 0) && /* Confused?         */
  1578.     (randint(4) > 1))       /* 75% random movement   */
  1579.     dir = randint(9);
  1580.     y = char_row;
  1581.     x = char_col;
  1582.     (void)mmove(dir, &y, &x);
  1583.  
  1584.     c_ptr = &cave[y][x];
  1585. /* Compute the digging ability of player; based on       */
  1586. /* strength, and type of tool used               */
  1587.     tabil = py.stats.use_stat[A_STR];
  1588.     i_ptr = &inventory[INVEN_WIELD];
  1589.  
  1590. /*
  1591.  * Don't let the player tunnel somewhere illegal, this is necessary to
  1592.  * prevent the player from getting a free attack by trying to tunnel
  1593.  * somewhere where it has no effect.  
  1594.  */
  1595.     if (c_ptr->fval < MIN_CAVE_WALL
  1596.     && (c_ptr->tptr == 0 || (t_list[c_ptr->tptr].tval != TV_RUBBLE
  1597.               && t_list[c_ptr->tptr].tval != TV_SECRET_DOOR))) {
  1598.     if (c_ptr->tptr == 0) {
  1599.         msg_print("Tunnel through what?  Empty air?!?");
  1600.         free_turn_flag = TRUE;
  1601.     } else {
  1602.         msg_print("You can't tunnel through that.");
  1603.         free_turn_flag = TRUE;
  1604.     }
  1605.     return;
  1606.     }
  1607.     if (c_ptr->cptr > 1) {
  1608.     m_ptr = &m_list[c_ptr->cptr];
  1609.     if (m_ptr->ml) {
  1610.         if (c_list[m_ptr->mptr].cdefense & UNIQUE)
  1611.         (void)sprintf(m_name, "%s", c_list[m_ptr->mptr].name);
  1612.         else
  1613.         (void)sprintf(m_name, "The %s", c_list[m_ptr->mptr].name);
  1614.     } else
  1615.         (void)strcpy(m_name, "Something");
  1616.     (void)sprintf(out_val, "%s is in your way!", m_name);
  1617.     msg_print(out_val);
  1618.  
  1619.     /* let the player attack the creature */
  1620.     if (py.flags.afraid < 1)
  1621.         py_attack(y, x);
  1622.     else
  1623.         msg_print("You are too afraid!");
  1624.     } else if (i_ptr->tval != TV_NOTHING) {
  1625.     if (TR_TUNNEL & i_ptr->flags)
  1626.         tabil += 25 + i_ptr->p1 * 50;
  1627.     else {
  1628.         tabil += (i_ptr->damage[0] * i_ptr->damage[1]) + i_ptr->tohit
  1629.         + i_ptr->todam;
  1630.     /* divide by two so that digging without shovel isn't too easy */
  1631.         tabil >>= 1;
  1632.     }
  1633.  
  1634.     if (weapon_heavy) {
  1635.         tabil += (py.stats.use_stat[A_STR] * 15) - i_ptr->weight;
  1636.         if (tabil < 0)
  1637.         tabil = 0;
  1638.     }
  1639.     /* Regular walls; Granite, magma intrusion, quartz vein  */
  1640.     /* Don't forget the boundary walls, made of titanium (255) */
  1641.     switch (c_ptr->fval) {
  1642.       case GRANITE_WALL:
  1643.         i = randint(1200) + 80;
  1644.         if (twall(y, x, tabil, i)) {
  1645.         msg_print("You have finished the tunnel.");
  1646.         check_view();
  1647.         } else
  1648.         count_msg_print("You tunnel into the granite wall.");
  1649.         break;
  1650.       case MAGMA_WALL:
  1651.         i = randint(600) + 10;
  1652.         if (twall(y, x, tabil, i)) {
  1653.         msg_print("You have finished the tunnel.");
  1654.         check_view();
  1655.         } else
  1656.         count_msg_print("You tunnel into the magma intrusion.");
  1657.         break;
  1658.       case QUARTZ_WALL:
  1659.         i = randint(400) + 10;
  1660.         if (twall(y, x, tabil, i)) {
  1661.         msg_print("You have finished the tunnel.");
  1662.         check_view();
  1663.         } else
  1664.         count_msg_print("You tunnel into the quartz vein.");
  1665.         break;
  1666.       case BOUNDARY_WALL:
  1667.         msg_print("This seems to be permanent rock.");
  1668.         break;
  1669.       default:
  1670.     /* Is there an object in the way?  (Rubble and secret doors) */
  1671.         if (c_ptr->tptr != 0) {
  1672.         /* Rubble.     */
  1673.         if (t_list[c_ptr->tptr].tval == TV_RUBBLE) {
  1674.             if (tabil > randint(180)) {
  1675.             (void)delete_object(y, x);
  1676.             msg_print("You have removed the rubble.");
  1677.             if (randint(10) == 1) {
  1678.                 place_object(y, x);
  1679.                 if (test_light(y, x))
  1680.                 msg_print("You have found something!");
  1681.             }
  1682.             lite_spot(y, x);
  1683.             check_view();
  1684.             } else
  1685.             count_msg_print("You dig in the rubble.");
  1686.         }
  1687.         /* Secret doors. */
  1688.         else if (t_list[c_ptr->tptr].tval == TV_SECRET_DOOR) {
  1689.             count_msg_print("You tunnel into the granite wall.");
  1690.             search(char_row, char_col, py.misc.srh);
  1691.         } else {
  1692.             msg_print("You can't tunnel through that.");
  1693.             free_turn_flag = TRUE;
  1694.         }
  1695.         } else {
  1696.         msg_print("Tunnel through what?  Empty air?!?");
  1697.         free_turn_flag = TRUE;
  1698.         }
  1699.         break;
  1700.     }
  1701.     } else
  1702.     msg_print("You dig with your hands, making no progress.");
  1703. }
  1704.  
  1705.  
  1706. /* Disarms a trap                    -RAK-     */
  1707. void 
  1708. disarm_trap()
  1709. {
  1710.     int                 y, x, level, tmp, dir, no_disarm;
  1711.     register int        tot, i;
  1712.     register cave_type *c_ptr;
  1713.     register inven_type *i_ptr;
  1714.     monster_type       *m_ptr;
  1715.     vtype               m_name, out_val;
  1716. #ifdef TARGET
  1717.     int temp = target_mode; /* targetting will screw up get_dir, so we save
  1718.                    target_mode, then turn it off -CFT */
  1719. #endif
  1720.  
  1721.     y = char_row;
  1722.     x = char_col;
  1723. #ifdef TARGET
  1724.     target_mode = FALSE;
  1725. #endif
  1726.     if (get_dir(NULL, &dir)) {
  1727.     (void)mmove(dir, &y, &x);
  1728.     c_ptr = &cave[y][x];
  1729.     no_disarm = FALSE;
  1730.     if (c_ptr->cptr > 1 && c_ptr->tptr != 0 &&
  1731.         (t_list[c_ptr->tptr].tval == TV_VIS_TRAP
  1732.          || t_list[c_ptr->tptr].tval == TV_CHEST)) {
  1733.         m_ptr = &m_list[c_ptr->cptr];
  1734.         if (m_ptr->ml)
  1735.         (void)sprintf(m_name, "The %s", c_list[m_ptr->mptr].name);
  1736.         else
  1737.         (void)strcpy(m_name, "Something");
  1738.         (void)sprintf(out_val, "%s is in your way!", m_name);
  1739.         msg_print(out_val);
  1740.     } else if (c_ptr->tptr != 0) {
  1741.         tot = py.misc.disarm + 2 * todis_adj() + stat_adj(A_INT)
  1742.         + (class_level_adj[py.misc.pclass][CLA_DISARM] * py.misc.lev / 3);
  1743.         if ((py.flags.blind > 0) || (no_light()))
  1744.         tot = tot / 10;
  1745.         if (py.flags.confused > 0)
  1746.         tot = tot / 10;
  1747.         if (py.flags.image > 0)
  1748.         tot = tot / 10;
  1749.         i_ptr = &t_list[c_ptr->tptr];
  1750.         i = i_ptr->tval;
  1751.         level = i_ptr->level;
  1752.         if (i == TV_VIS_TRAP) {/* Floor trap    */
  1753.         if ((tot + 100 - level) > randint(100)) {
  1754.             msg_print("You have disarmed the trap.");
  1755.             py.misc.exp += i_ptr->p1;
  1756.             (void)delete_object(y, x);
  1757.         /* make sure we move onto the trap even if confused */
  1758.             tmp = py.flags.confused;
  1759.             py.flags.confused = 0;
  1760.             move_char(dir, FALSE);
  1761.             py.flags.confused = tmp;
  1762.             prt_experience();
  1763.         }
  1764.         /* avoid randint(0) call */
  1765.         else if ((tot > 5) && (randint(tot) > 5))
  1766.             count_msg_print("You failed to disarm the trap.");
  1767.         else {
  1768.             msg_print("You set the trap off!");
  1769.         /* make sure we move onto the trap even if confused */
  1770.             tmp = py.flags.confused;
  1771.             py.flags.confused = 0;
  1772.             move_char(dir, FALSE);
  1773.             py.flags.confused += tmp;
  1774.         }
  1775.         } else if (i == TV_CHEST) {
  1776.         if (!known2_p(i_ptr)) {
  1777.             msg_print("I don't see a trap.");
  1778.             free_turn_flag = TRUE;
  1779.         } else if (CH_TRAPPED & i_ptr->flags) {
  1780.             if ((tot - level) > randint(100)) {
  1781.             i_ptr->flags &= ~CH_TRAPPED;
  1782.             if (CH_LOCKED & i_ptr->flags)
  1783.                 i_ptr->name2 = SN_LOCKED;
  1784.             else
  1785.                 i_ptr->name2 = SN_DISARMED;
  1786.             msg_print("You have disarmed the chest.");
  1787.             known2(i_ptr);
  1788.             py.misc.exp += level;
  1789.             prt_experience();
  1790.             } else if ((tot > 5) && (randint(tot) > 5))
  1791.             count_msg_print("You failed to disarm the chest.");
  1792.             else {
  1793.             msg_print("You set a trap off!");
  1794.             known2(i_ptr);
  1795.             chest_trap(y, x);
  1796.             }
  1797.         } else {
  1798.             msg_print("The chest was not trapped.");
  1799.             free_turn_flag = TRUE;
  1800.         }
  1801.         } else
  1802.         no_disarm = TRUE;
  1803.     } else
  1804.         no_disarm = TRUE;
  1805.  
  1806.     if (no_disarm) {
  1807.         msg_print("I do not see anything to disarm there.");
  1808.         free_turn_flag = TRUE;
  1809.     }
  1810.     }
  1811. #ifdef TARGET
  1812.     target_mode = temp;
  1813. #endif
  1814. }
  1815.  
  1816.  
  1817. /*
  1818.  * An enhanced look, with peripheral vision. Looking all 8    -CJS-
  1819.  * directions will see everything which ought to be visible. Can specify
  1820.  * direction 5, which looks in all directions. 
  1821.  *
  1822.  * For the purpose of hindering vision, each place is regarded as a diamond just
  1823.  * touching its four immediate neighbours. A diamond is opaque if it is a
  1824.  * wall, or shut door, or something like that. A place is visible if any part
  1825.  * of its diamond is visible: i.e. there is a line from the view point to
  1826.  * part of the diamond which does not pass through any opaque diamonds. 
  1827.  *
  1828.  * Consider the following situation: 
  1829.  *
  1830.  * @....                X    X   X    X   X .##..               /
  1831.  * \ / \ / \ / \ / \ .....              X @ X . X . X 1 X . X \ / \
  1832.  * / \ / \ / \ / X    X   X    X   X Expanded view, with       / \ / \ /
  1833.  * \ / \ / \ diamonds inscribed      X . X # X # X 2 X . X about each point,      
  1834.  * \ / \ / \ / \ / \ / and some locations        X    X   X    X   X
  1835.  * numbered.           / \ / \ / \ / \ / \ X . X . X . X 3 X 4 X \ / \ /
  1836.  * \ / \ / \ / X    X   X    X   X - Location 1 is fully visible. -
  1837.  * Location 2 is visible, even though partially obscured. - Location 3 is
  1838.  * invisible, but if either # were transparent, it would be visible. -
  1839.  * Location 4 is completely obscured by a single #. 
  1840.  *
  1841.  * The function which does the work is look_ray. It sets up its own co-ordinate
  1842.  * frame (global variables map back to the dungeon frame) and looks for
  1843.  * everything between two angles specified from a central line. It is
  1844.  * recursive, and each call looks at stuff visible along a line parallel to
  1845.  * the center line, and a set distance away from it. A diagonal look uses
  1846.  * more extreme peripheral vision from the closest horizontal and vertical
  1847.  * directions; horizontal or vertical looks take a call for each side of the
  1848.  * central line. 
  1849.  */
  1850.  
  1851. /*
  1852.  * Globally accessed variables: gl_nseen counts the number of places where
  1853.  * something is seen. gl_rock indicates a look for rock or objects. 
  1854.  *
  1855.  * The others map co-ords in the ray frame to dungeon co-ords. 
  1856.  *
  1857.  * dungeon y = char_row     + gl_fyx * (ray x)  + gl_fyy * (ray y) dungeon x =
  1858.  * char_col     + gl_fxx * (ray x)  + gl_fxy * (ray y) 
  1859.  */
  1860. static int          gl_fxx, gl_fxy, gl_fyx, gl_fyy;
  1861. static int          gl_nseen, gl_noquery;
  1862. static int          gl_rock;
  1863.  
  1864. /*
  1865.  * Intended to be indexed by dir/2, since is only relevant to horizontal or
  1866.  * vertical directions. 
  1867.  */
  1868. static int          set_fxy[] = {0, 1, 0, 0, -1};
  1869. static int          set_fxx[] = {0, 0, -1, 1, 0};
  1870. static int          set_fyy[] = {0, 0, 1, -1, 0};
  1871. static int          set_fyx[] = {0, 1, 0, 0, -1};
  1872.  
  1873. /* Map diagonal-dir/2 to a normal-dir/2. */
  1874. static int          map_diag1[] = {1, 3, 0, 2, 4};
  1875. static int          map_diag2[] = {2, 1, 0, 4, 3};
  1876.  
  1877. #define GRADF    10000           /* Any sufficiently big number will do */
  1878.  
  1879. /*
  1880.  * Look at what we can see. This is a free move. 
  1881.  *
  1882.  * Prompts for a direction, and then looks at every object in turn within a cone
  1883.  * of vision in that direction. For each object, the cursor is moved over the
  1884.  * object, a description is given, and we wait for the user to type
  1885.  * something. Typing ESCAPE will abort the entire look. 
  1886.  *
  1887.  * Looks first at real objects and monsters, and looks at rock types only after
  1888.  * all other things have been seen.  Only looks at rock types if the
  1889.  * highlight_seams option is set. 
  1890.  */
  1891.  
  1892. void 
  1893. look()
  1894. {
  1895.     register int        i, abort;
  1896.     int                 dir, dummy;
  1897.  
  1898.     if (py.flags.blind > 0)
  1899.     msg_print("You can't see a damn thing!");
  1900.     else if (py.flags.image > 0)
  1901.     msg_print("You can't believe what you are seeing! It's like a dream!");
  1902.     else if (get_alldir("Look which direction? ", &dir)) {
  1903.     abort = FALSE;
  1904.     gl_nseen = 0;
  1905.     gl_rock = 0;
  1906.     gl_noquery = FALSE;       /* Have to set this up for the look_see */
  1907.     if (look_see(0, 0, &dummy))
  1908.         abort = TRUE;
  1909.     else {
  1910.         do {
  1911.         abort = FALSE;
  1912.         if (dir == 5) {
  1913.             for (i = 1; i <= 4; i++) {
  1914.             gl_fxx = set_fxx[i];
  1915.             gl_fyx = set_fyx[i];
  1916.             gl_fxy = set_fxy[i];
  1917.             gl_fyy = set_fyy[i];
  1918.             if (look_ray(0, 2 * GRADF - 1, 1)) {
  1919.                 abort = TRUE;
  1920.                 break;
  1921.             }
  1922.             gl_fxy = (-gl_fxy);
  1923.             gl_fyy = (-gl_fyy);
  1924.             if (look_ray(0, 2 * GRADF, 2)) {
  1925.                 abort = TRUE;
  1926.                 break;
  1927.             }
  1928.             }
  1929.         } else if ((dir & 1) == 0) {    /* Straight directions */
  1930.             i = dir >> 1;
  1931.             gl_fxx = set_fxx[i];
  1932.             gl_fyx = set_fyx[i];
  1933.             gl_fxy = set_fxy[i];
  1934.             gl_fyy = set_fyy[i];
  1935.             if (look_ray(0, GRADF, 1))
  1936.             abort = TRUE;
  1937.             else {
  1938.             gl_fxy = (-gl_fxy);
  1939.             gl_fyy = (-gl_fyy);
  1940.             abort = look_ray(0, GRADF, 2);
  1941.             }
  1942.         } else {
  1943.             i = map_diag1[dir >> 1];
  1944.             gl_fxx = set_fxx[i];
  1945.             gl_fyx = set_fyx[i];
  1946.             gl_fxy = (-set_fxy[i]);
  1947.             gl_fyy = (-set_fyy[i]);
  1948.             if (look_ray(1, 2 * GRADF, GRADF))
  1949.             abort = TRUE;
  1950.             else {
  1951.             i = map_diag2[dir >> 1];
  1952.             gl_fxx = set_fxx[i];
  1953.             gl_fyx = set_fyx[i];
  1954.             gl_fxy = set_fxy[i];
  1955.             gl_fyy = set_fyy[i];
  1956.             abort = look_ray(1, 2 * GRADF - 1, GRADF);
  1957.             }
  1958.         }
  1959.         }
  1960.         while (abort == FALSE && highlight_seams && (++gl_rock < 2));
  1961.         if (abort)
  1962.         msg_print("--Aborting look--");
  1963.         else {
  1964.         if (gl_nseen) {
  1965.             if (dir == 5)
  1966.             msg_print("That's all you see.");
  1967.             else
  1968.             msg_print("That's all you see in that direction.");
  1969.         } else if (dir == 5)
  1970.             msg_print("You see nothing of interest.");
  1971.         else
  1972.             msg_print("You see nothing of interest in that direction.");
  1973.         }
  1974.     }
  1975.     }
  1976. }
  1977.  
  1978. /* Look at everything within a cone of vision between two ray
  1979.    lines emanating from the player, and y or more places away
  1980.    from the direct line of view. This is recursive.
  1981.  
  1982.    Rays are specified by gradients, y over x, multiplied by
  1983.    2*GRADF. This is ONLY called with gradients between 2*GRADF
  1984.    (45 degrees) and 1 (almost horizontal).
  1985.  
  1986.    (y axis)/ angle from
  1987.      ^      /        ___ angle to
  1988.      |     /     ___
  1989.   ...|../.....___.................... parameter y (look at things in the
  1990.      | /   ___                  cone, and on or above this line)
  1991.      |/ ___
  1992.      @-------------------->   direction in which you are looking. (x axis)
  1993.      |
  1994.      | */
  1995.  
  1996. static int 
  1997. look_ray(y, from, to)
  1998.     int                 y, from, to;
  1999. {
  2000.     register int        max_x, x;
  2001.     int                 transparent;
  2002.  
  2003. /*
  2004.  * from is the larger angle of the ray, since we scan towards the center
  2005.  * line. If from is smaller, then the ray does not exist. 
  2006.  */
  2007.     if (from <= to || y > MAX_SIGHT)
  2008.     return FALSE;
  2009. /*
  2010.  * Find first visible location along this line. Minimum x such that (2x-1)/x
  2011.  * < from/GRADF <=> x > GRADF(2x-1)/from. This may be called with y=0 whence
  2012.  * x will be set to 0. Thus we need a special fix. 
  2013.  */
  2014.     x = (long)GRADF    *(2 * y - 1) / from + 1;
  2015.  
  2016.     if (x <= 0)
  2017.     x = 1;
  2018.  
  2019. /*
  2020.  * Find last visible location along this line. Maximum x such that (2x+1)/x >
  2021.  * to/GRADF <=> x < GRADF(2x+1)/to 
  2022.  */
  2023.     max_x = ((long)GRADF * (2 * y + 1) - 1) / to;
  2024.     if (max_x > MAX_SIGHT)
  2025.     max_x = MAX_SIGHT;
  2026.     if (max_x < x)
  2027.     return FALSE;
  2028.  
  2029. /*
  2030.  * gl_noquery is a HACK to prevent doubling up on direct lines of sight. If
  2031.  * 'to' is    greater than 1, we do not really look at stuff along the
  2032.  * direct line of sight, but we do have to see what is opaque for the
  2033.  * purposes of obscuring other objects. 
  2034.  */
  2035.     if ((y == 0 && to > 1) || (y == x && from < GRADF * 2))
  2036.     gl_noquery = TRUE;
  2037.     else
  2038.     gl_noquery = FALSE;
  2039.     if (look_see(x, y, &transparent))
  2040.     return TRUE;
  2041.     if (y == x)
  2042.     gl_noquery = FALSE;
  2043.     if (transparent)
  2044.     goto init_transparent;
  2045.  
  2046.     for (;;) {
  2047.     /* Look down the window we've found. */
  2048.     if (look_ray(y + 1, from, (int)((2 * y + 1) * (long)GRADF / x)))
  2049.         return TRUE;
  2050.     /* Find the start of next window. */
  2051.     do {
  2052.         if (x == max_x)
  2053.         return FALSE;
  2054.     /* See if this seals off the scan. (If y is zero, then it will.) */
  2055.         from = (2 * y - 1) * (long)GRADF / x;
  2056.         if (from <= to)
  2057.         return FALSE;
  2058.         x++;
  2059.         if (look_see(x, y, &transparent))
  2060.         return TRUE;
  2061.     }
  2062.     while (!transparent);
  2063. init_transparent:
  2064.     /* Find the end of this window of visibility. */
  2065.     do {
  2066.         if (x == max_x)
  2067.         /* The window is trimmed by an earlier limit. */
  2068.         return look_ray(y + 1, from, to);
  2069.         x++;
  2070.         if (look_see(x, y, &transparent))
  2071.         return TRUE;
  2072.     }
  2073.     while (transparent);
  2074.     }
  2075. }
  2076.  
  2077. static int 
  2078. look_see(x, y, transparent)
  2079.     register int        x, y;
  2080.     int                *transparent;
  2081. {
  2082.     const char         *dstring,*string;
  2083.     char               query = 'a';
  2084.     register cave_type *c_ptr;
  2085.     register int        j;
  2086.     bigvtype            out_val, tmp_str;
  2087.  
  2088.     if (x < 0 || y < 0 || y > x) {
  2089.     (void)sprintf(tmp_str, "Illegal call to look_see(%d, %d)", x, y);
  2090.     msg_print(tmp_str);
  2091.     }
  2092.     if (x == 0 && y == 0)
  2093.     dstring = "You are on";
  2094.     else
  2095.     dstring = "You see";
  2096.     j = char_col + gl_fxx * x + gl_fxy * y;
  2097.     y = char_row + gl_fyx * x + gl_fyy * y;
  2098.     x = j;
  2099.     if (!panel_contains(y, x)) {
  2100.     *transparent = FALSE;
  2101.     return FALSE;
  2102.     }
  2103.     c_ptr = &cave[y][x];
  2104.     *transparent = c_ptr->fval <= MAX_OPEN_SPACE;
  2105.     if (gl_noquery)
  2106.     return FALSE;           /* Don't look at a direct line of sight. A
  2107.                     * hack. */
  2108.     out_val[0] = 0;
  2109.     if (gl_rock == 0 && c_ptr->cptr > 1 && m_list[c_ptr->cptr].ml) {
  2110.     j = m_list[c_ptr->cptr].mptr;
  2111.     (void)sprintf(out_val, "%s %s %s (%s).  [(r)ecall]",
  2112.               dstring,
  2113.               is_a_vowel(c_list[j].name[0]) ? "an" : "a",
  2114.               c_list[j].name,
  2115.               look_mon_desc((int)c_ptr->cptr));
  2116.     dstring = "It is on";
  2117.     prt(out_val, 0, 0);
  2118.     move_cursor_relative(y, x);
  2119.     query = inkey();
  2120.     if (query == 'r' || query == 'R') {
  2121.         save_screen();
  2122.         query = roff_recall(j);
  2123.         restore_screen();
  2124.     }
  2125.     }
  2126.     if (c_ptr->tl || c_ptr->pl || c_ptr->fm) {
  2127.     if (c_ptr->tptr != 0) {
  2128.         if (t_list[c_ptr->tptr].tval == TV_SECRET_DOOR)
  2129.         goto granite;
  2130.         if (gl_rock == 0 && t_list[c_ptr->tptr].tval != TV_INVIS_TRAP) {
  2131.         objdes(tmp_str, &t_list[c_ptr->tptr], TRUE);
  2132.         (void)sprintf(out_val, "%s %s.  ---pause---", dstring, tmp_str);
  2133.         dstring = "It is in";
  2134.         prt(out_val, 0, 0);
  2135.         move_cursor_relative(y, x);
  2136.         query = inkey();
  2137.         }
  2138.     }
  2139.     if ((gl_rock || out_val[0]) && c_ptr->fval >= MIN_CLOSED_SPACE) {
  2140.         switch (c_ptr->fval) {
  2141.           case BOUNDARY_WALL:
  2142.           case GRANITE_WALL:
  2143.     granite:
  2144.         /* Granite is only interesting if it contains something. */
  2145.         if (out_val[0])
  2146.             string = "a granite wall";
  2147.         else
  2148.             string = NULL; /* In case we jump here */
  2149.         break;
  2150.           case MAGMA_WALL:
  2151.         string = "some dark rock";
  2152.         break;
  2153.           case QUARTZ_WALL:
  2154.         string = "a quartz vein";
  2155.         break;
  2156.           default:
  2157.         string = NULL;
  2158.         break;
  2159.         }
  2160.         if (string) {
  2161.         (void)sprintf(out_val, "%s %s.  ---pause---", dstring, string);
  2162.         prt(out_val, 0, 0);
  2163.         move_cursor_relative(y, x);
  2164.         query = inkey();
  2165.         }
  2166.     }
  2167.     }
  2168.     if (out_val[0]) {
  2169.     gl_nseen++;
  2170.     if (query == ESCAPE)
  2171.         return TRUE;
  2172.     }
  2173.     return FALSE;
  2174. }
  2175.  
  2176.  
  2177. static void 
  2178. inven_throw(item_val, t_ptr)
  2179.     int                 item_val;
  2180.     inven_type         *t_ptr;
  2181. {
  2182.     register inven_type *i_ptr;
  2183.  
  2184.     i_ptr = &inventory[item_val];
  2185.     *t_ptr = *i_ptr;
  2186.     if (i_ptr->number > 1) {
  2187.     t_ptr->number = 1;
  2188.     i_ptr->number--;
  2189.     inven_weight -= i_ptr->weight;
  2190.     py.flags.status |= PY_STR_WGT;
  2191.     } else
  2192.     inven_destroy(item_val);
  2193. }
  2194.  
  2195.  
  2196. /*
  2197.  * Obtain the hit and damage bonuses and the maximum distance for a thrown
  2198.  * missile. 
  2199.  */
  2200. static void 
  2201. facts(i_ptr, tbth, tpth, tdam, tdis, thits)
  2202.     register inven_type *i_ptr;
  2203.     int                *tbth, *tpth, *tdam, *tdis, *thits;
  2204. {
  2205.     register int        tmp_weight;
  2206.     int                 tmp_tohit; /* Just a dummy -EAM */
  2207.  
  2208.     if (i_ptr->weight < 1)
  2209.     tmp_weight = 1;
  2210.     else
  2211.     tmp_weight = i_ptr->weight;
  2212.  
  2213. /* Throwing objects             */
  2214.     *tdam = pdamroll(i_ptr->damage) + i_ptr->todam;
  2215.     *tbth = py.misc.bthb * 75 / 100;
  2216.     *tpth = py.misc.ptohit + i_ptr->tohit;
  2217.  
  2218. /* Add this back later if the correct throwing device. -CJS- */
  2219.     if (inventory[INVEN_WIELD].tval != TV_NOTHING)
  2220.     *tpth -= inventory[INVEN_WIELD].tohit;
  2221.  
  2222.     *tdis = (((py.stats.use_stat[A_STR] + 20) * 10) / tmp_weight);
  2223.     if (*tdis > 10)
  2224.     *tdis = 10;
  2225.  
  2226. /*
  2227.  * EAM - Default to single shot or throw but rangers do better with any kind
  2228.  * of bow 
  2229.  */
  2230.     *thits = 1;
  2231.  
  2232. /*
  2233.  * multiply damage bonuses instead of adding, when have proper missile/weapon
  2234.  * combo, this makes them much more useful 
  2235.  */
  2236.  
  2237. /* Using Bows,  slings,  or crossbows     */
  2238.     if (inventory[INVEN_WIELD].tval == TV_BOW)
  2239.     switch (inventory[INVEN_WIELD].subval) {
  2240.       case 20:
  2241.         if (i_ptr->tval == TV_SLING_AMMO) {    /* Sling and ammo */
  2242.         *tbth = py.misc.bthb;
  2243.         *tpth += 2 * inventory[INVEN_WIELD].tohit;
  2244.         *tdam += inventory[INVEN_WIELD].todam;
  2245.         *tdam = *tdam * 2;
  2246.         *tdis = 20;
  2247.         }
  2248.         break;
  2249.       case 1:
  2250.         if (i_ptr->tval == TV_ARROW) {    /* Short Bow and Arrow     */
  2251.         *tbth = py.misc.bthb;
  2252.         *tpth += 2 * inventory[INVEN_WIELD].tohit;
  2253.         *tdam += inventory[INVEN_WIELD].todam;
  2254.         *tdam = *tdam * 2;
  2255.         *tdis = 25;
  2256.         if (py.misc.pclass == 4)
  2257.             *thits = attack_blows((int)inventory[INVEN_WIELD].weight,
  2258.                       &tmp_tohit);
  2259.         }
  2260.         break;
  2261.       case 2:
  2262.         if (i_ptr->tval == TV_ARROW) {    /* Long Bow and Arrow     */
  2263.         *tbth = py.misc.bthb;
  2264.         *tpth += 2 * inventory[INVEN_WIELD].tohit;
  2265.         *tdam += inventory[INVEN_WIELD].todam;
  2266.         *tdam = *tdam * 3;
  2267.         *tdis = 30;
  2268.         if (py.misc.pclass == 4)
  2269.             *thits = attack_blows((int)inventory[INVEN_WIELD].weight,
  2270.                       &tmp_tohit);
  2271.         }
  2272.         break;
  2273. #if 0
  2274.       case 4:
  2275.         if (i_ptr->tval == TV_ARROW) {    /* Composite Bow and Arrow */
  2276.         *tbth = py.misc.bthb;
  2277.         *tpth += 2 * inventory[INVEN_WIELD].tohit;
  2278.         *tdam += inventory[INVEN_WIELD].todam;
  2279.         *tdam = *tdam * 4;
  2280.         *tdis = 35;
  2281.         if (py.misc.pclass == 4)
  2282.             *thits = attack_blows((int)inventory[INVEN_WIELD].weight,
  2283.                       &tmp_tohit);
  2284.         }
  2285.         break;
  2286. #endif                   /* 0 */
  2287.       case 10:
  2288.         if (i_ptr->tval == TV_BOLT) {    /* Light Crossbow and Bolt */
  2289.         *tbth = py.misc.bthb;
  2290.         *tpth += 2 * inventory[INVEN_WIELD].tohit;
  2291.         *tdam += inventory[INVEN_WIELD].todam;
  2292.         *tdam = *tdam * 3;
  2293.         *tdis = 25;
  2294.         }
  2295.         break;
  2296.       case 11:
  2297.         if (i_ptr->tval == TV_BOLT) {    /* Heavy Crossbow and Bolt */
  2298.         *tbth = py.misc.bthb;
  2299.         *tpth += 2 * inventory[INVEN_WIELD].tohit;
  2300.         *tdam += inventory[INVEN_WIELD].todam;
  2301.         *tdam = *tdam * 4;
  2302.         *tdis = 35;
  2303.         }
  2304.         break;
  2305.     }
  2306. }
  2307.  
  2308.  
  2309. static void 
  2310. drop_throw(y, x, t_ptr)
  2311.     int                 y, x;
  2312.     inven_type         *t_ptr;
  2313. {
  2314.     register int        i, j, k;
  2315.     int                 flag, cur_pos;
  2316.     bigvtype            out_val, tmp_str;
  2317.     register cave_type *c_ptr;
  2318.  
  2319.     flag = FALSE;
  2320.     i = y;
  2321.     j = x;
  2322.     k = 0;
  2323.     if (randint(10) > 1 || t_ptr->flags2 & TR_ARTIFACT) {    /* no artifact arrows
  2324.                                  * yet */
  2325.     do {
  2326.         if (in_bounds(i, j)) {
  2327.         c_ptr = &cave[i][j];
  2328.         if (c_ptr->fval <= MAX_OPEN_SPACE && c_ptr->tptr == 0)
  2329.             flag = TRUE;
  2330.         }
  2331.         if (!flag) {
  2332.         i = y + randint(3) - 2;
  2333.         j = x + randint(3) - 2;
  2334.         k++;
  2335.         }
  2336.     }
  2337.     while ((!flag) && (k <= 9));
  2338.     }
  2339.     if (!flag && t_ptr->flags2 & TR_ARTIFACT) {
  2340.     flag = FALSE;
  2341.     i = y;
  2342.     j = x;
  2343.     k = 0;
  2344.     do {
  2345.         if (in_bounds(i, j)) {
  2346.         c_ptr = &cave[i][j];
  2347.         if (c_ptr->fval <= MAX_OPEN_SPACE &&
  2348.             !(((t_list[c_ptr->tptr].tval >= TV_MIN_WEAR) &&
  2349.                (t_list[c_ptr->tptr].tval <= TV_MAX_WEAR) &&
  2350.                (t_list[c_ptr->tptr].flags2 & TR_ARTIFACT))
  2351.               || (t_list[c_ptr->tptr].tval == TV_UP_STAIR)
  2352.               || (t_list[c_ptr->tptr].tval == TV_DOWN_STAIR)
  2353.               || (t_list[c_ptr->tptr].tval == TV_STORE_DOOR)))
  2354.             flag = TRUE;
  2355.         }
  2356.         if (!flag) {
  2357.         int                 newi, newj;
  2358.  
  2359.         do {
  2360.             newi = i + randint(3) - 2;
  2361.             newj = j + randint(3) - 2;
  2362.         } while (!in_bounds(newi, newj) ||
  2363.              (cave[newi][newj].fval > MAX_OPEN_SPACE));
  2364.         i = newi;
  2365.         j = newj;
  2366.         k++;
  2367.         }
  2368.     } while ((!flag) && (k <= 50));
  2369.     if (flag && (cave[i][j].tptr != 0))
  2370.         (void)delete_object(i, j);
  2371.     }
  2372.     if (flag) {
  2373.     cur_pos = popt();
  2374.     cave[i][j].tptr = cur_pos;
  2375.     t_list[cur_pos] = *t_ptr;
  2376.     lite_spot(i, j);
  2377.     } else {
  2378.     objdes(tmp_str, t_ptr, FALSE);
  2379.     (void)sprintf(out_val, "The %s disappears.", tmp_str);
  2380.     msg_print(out_val);
  2381.     }
  2382. }
  2383.  
  2384. /* Throw an object across the dungeon.        -RAK-     */
  2385. /* Note: Flasks of oil do fire damage                 */
  2386. /* Note: Extra damage and chance of hitting when missiles are used */
  2387. /* with correct weapon.  I.E.  wield bow and throw arrow.     */
  2388. /* Note: Some characters will now get multiple shots per turn -EAM */
  2389. void 
  2390. throw_object()
  2391. {
  2392.     int                 item_val, tbth, tpth, tdam, tdis;
  2393.     int                 y, x, oldy, oldx, cur_dis, dir;
  2394.     int                 flag, visible;
  2395.     int                 thits, max_shots;
  2396.     bigvtype            out_val, tmp_str;
  2397.     inven_type          throw_obj;
  2398.     register cave_type *c_ptr;
  2399.     register monster_type *m_ptr;
  2400.     register int        i;
  2401.     char                tchar;
  2402.  
  2403.     if (inven_ctr == 0) {
  2404.     msg_print("But you are not carrying anything.");
  2405.     free_turn_flag = TRUE;
  2406.     } else if (get_item(&item_val, "Fire/Throw which one?", 0, inven_ctr - 1, 0)) {
  2407.     if (get_dir(NULL, &dir)) {
  2408.         desc_remain(item_val);
  2409.         if (py.flags.confused > 0) {
  2410.         msg_print("You are confused.");
  2411.         do {
  2412.             dir = randint(9);
  2413.         }
  2414.         while (dir == 5);
  2415.         }
  2416.         max_shots = inventory[item_val].number;
  2417.         inven_throw(item_val, &throw_obj);
  2418.         facts(&throw_obj, &tbth, &tpth, &tdam, &tdis, &thits);
  2419.         if (thits > max_shots)
  2420.         thits = max_shots;
  2421.         tchar = throw_obj.tchar;
  2422.     /* EAM Start loop over multiple shots */
  2423.         while (thits-- > 0) {
  2424.         if (inventory[INVEN_WIELD].subval == 12)
  2425.             tpth -= 10;
  2426.         flag = FALSE;
  2427.         y = char_row;
  2428.         x = char_col;
  2429.         oldy = char_row;
  2430.         oldx = char_col;
  2431.         cur_dis = 0;
  2432.         do {
  2433.             (void)mmove(dir, &y, &x);
  2434.             cur_dis++;
  2435.             lite_spot(oldy, oldx);
  2436.             if (cur_dis > tdis)
  2437.             flag = TRUE;
  2438.             c_ptr = &cave[y][x];
  2439.             if ((c_ptr->fval <= MAX_OPEN_SPACE) && (!flag)) {
  2440.             if (c_ptr->cptr > 1) {
  2441.                 flag = TRUE;
  2442.                 m_ptr = &m_list[c_ptr->cptr];
  2443.                 tbth = tbth - cur_dis;
  2444.             /*
  2445.              * if monster not lit, make it much more difficult to
  2446.              * hit, subtract off most bonuses, and reduce bthb
  2447.              * depending on distance 
  2448.              */
  2449.                 if (!m_ptr->ml)
  2450.                 tbth = (tbth / (cur_dis + 2))
  2451.                     - (py.misc.lev *
  2452.                        class_level_adj[py.misc.pclass][CLA_BTHB] / 2)
  2453.                     - (tpth * (BTH_PLUS_ADJ - 1));
  2454.                 if (test_hit(tbth, (int)py.misc.lev, tpth,
  2455.                    (int)c_list[m_ptr->mptr].ac, CLA_BTHB)) {
  2456.                 i = m_ptr->mptr;
  2457.                 objdes(tmp_str, &throw_obj, FALSE);
  2458.                 /* Does the player know what he's fighting?       */
  2459.                 if (!m_ptr->ml) {
  2460.                     (void)sprintf(out_val,
  2461.                        "The %s finds a mark.", tmp_str);
  2462.                     visible = FALSE;
  2463.                 } else {
  2464.                     if (c_list[i].cdefense & UNIQUE)
  2465.                     (void)sprintf(out_val, "The %s hits %s.",
  2466.                            tmp_str, c_list[i].name);
  2467.                     else
  2468.                     (void)sprintf(out_val, "The %s hits the %s.",
  2469.                            tmp_str, c_list[i].name);
  2470.                     visible = TRUE;
  2471.                 }
  2472.                 msg_print(out_val);
  2473.                 tdam = tot_dam(&throw_obj, tdam, i);
  2474.                 tdam = critical_blow((int)throw_obj.weight,
  2475.                              tpth, tdam, CLA_BTHB);
  2476.                 if (tdam < 0)
  2477.                     tdam = 0;
  2478.                 /*
  2479.                  * always print fear msgs, so player can stop
  2480.                  * shooting -CWS 
  2481.                  */
  2482.                 i = mon_take_hit((int)c_ptr->cptr, tdam, TRUE);
  2483.                 if (i < 0) {
  2484.                     char                buf[100];
  2485.                     char                cdesc[100];
  2486.                     if (visible) {
  2487.                     if (c_list[i].cdefense & UNIQUE)
  2488.                         sprintf(cdesc, "%s", c_list[m_ptr->mptr].name);
  2489.                     else
  2490.                         sprintf(cdesc, "The %s", c_list[m_ptr->mptr].name);
  2491.                     } else
  2492.                     strcpy(cdesc, "It");
  2493.                     (void)sprintf(buf,
  2494.                           pain_message((int)c_ptr->cptr,
  2495.                                    (int)tdam), cdesc);
  2496.                     msg_print(buf);
  2497.                 }
  2498.                 if (i >= 0) {
  2499.                     if (!visible)
  2500.                     msg_print("You have killed something!");
  2501.                     else {
  2502.                     if (c_list[i].cdefense & UNIQUE)
  2503.                         (void)sprintf(out_val, "You have killed %s.",
  2504.                               c_list[i].name);
  2505.                     else
  2506.                         (void)sprintf(out_val, "You have killed the %s.",
  2507.                               c_list[i].name);
  2508.                     msg_print(out_val);
  2509.                     }
  2510.                     prt_experience();
  2511.                 }
  2512.                 } else
  2513.                 drop_throw(oldy, oldx, &throw_obj);
  2514.             } else {   /* do not test c_ptr->fm here */
  2515.                 if (panel_contains(y, x) && (py.flags.blind < 1)
  2516.                 && (c_ptr->tl || c_ptr->pl)) {
  2517.                 print(tchar, y, x);
  2518.                 put_qio();    /* show object moving */
  2519. #ifdef MSDOS
  2520.                 delay(8 * delay_spd);    /* milliseconds */
  2521. #else
  2522.                 usleep(8000 * delay_spd);    /* useconds */
  2523. #endif
  2524.                 }
  2525.             }
  2526.             } else {
  2527.             flag = TRUE;
  2528.             drop_throw(oldy, oldx, &throw_obj);
  2529.             }
  2530.             oldy = y;
  2531.             oldx = x;
  2532.         }
  2533.         while (!flag);
  2534.         if (thits > 0) {   /* triple crossbow check -- not really
  2535.                     * needed */
  2536.             if (inventory[INVEN_WIELD].subval != 12) {
  2537.             (void)sprintf(out_val, "Keep shooting?");
  2538.             if (get_check(out_val)) {
  2539.                 desc_remain(item_val);
  2540.                 inven_throw(item_val, &throw_obj);
  2541.             } else
  2542.                 thits = 0;
  2543.             } else {
  2544.             desc_remain(item_val);
  2545.             inven_throw(item_val, &throw_obj);
  2546.             }
  2547.         }
  2548.         }
  2549.     } /* EAM end loop over multiple shots */
  2550.     }
  2551. }
  2552.  
  2553.  
  2554. /*
  2555.  * Make a bash attack on someone.                -CJS- Used to
  2556.  * be part of bash above. 
  2557.  */
  2558. static void 
  2559. py_bash(y, x)
  2560.     int                 y, x;
  2561. {
  2562.     int                 monster, k, avg_max_hp, base_tohit, monptr;
  2563.     register creature_type *c_ptr;
  2564.     register monster_type *m_ptr;
  2565.     vtype               m_name, out_val;
  2566.  
  2567.     monster = cave[y][x].cptr;
  2568.     m_ptr = &m_list[monster];
  2569.     monptr = m_ptr->mptr;
  2570.     c_ptr = &c_list[monptr];
  2571.     m_ptr->csleep = 0;
  2572. /* Does the player know what he's fighting?       */
  2573.     if (!m_ptr->ml)
  2574.     (void)strcpy(m_name, "it");
  2575.     else {
  2576.     if (c_list[monptr].cdefense & UNIQUE)
  2577.         (void)sprintf(m_name, "%s", c_list[monptr].name);
  2578.     else
  2579.         (void)sprintf(m_name, "the %s", c_list[monptr].name);
  2580.     }
  2581.     base_tohit = py.stats.use_stat[A_STR] + inventory[INVEN_ARM].weight / 2
  2582.     + py.misc.wt / 10;
  2583.     if (!m_ptr->ml)
  2584.     base_tohit = (base_tohit / 2) - (py.stats.use_stat[A_DEX] * (BTH_PLUS_ADJ - 1))
  2585.         - (py.misc.lev * class_level_adj[py.misc.pclass][CLA_BTH] / 2);
  2586.  
  2587.     if (test_hit(base_tohit, (int)py.misc.lev,
  2588.          (int)py.stats.use_stat[A_DEX], (int)c_ptr->ac, CLA_BTH)) {
  2589.     (void)sprintf(out_val, "You hit %s.", m_name);
  2590.     msg_print(out_val);
  2591.     k = pdamroll(inventory[INVEN_ARM].damage);
  2592.     k = critical_blow((int)(inventory[INVEN_ARM].weight / 4
  2593.                 + py.stats.use_stat[A_STR]), 0, k, CLA_BTH);
  2594.     k += py.misc.wt / 60 + 3;
  2595.  
  2596.     if (k < 0)
  2597.         k = 0;           /* no neg damage! */
  2598.  
  2599.     /* See if we done it in.                     */
  2600.     if (mon_take_hit(monster, k, TRUE) >= 0) {
  2601.         if ((c_list[monptr].cdefense & (DEMON|UNDEAD|MINDLESS)) ||
  2602.         (c_list[monptr].cchar == 'E') ||
  2603.         (c_list[monptr].cchar == 'v') ||
  2604.         (c_list[monptr].cchar == 'g'))
  2605.         (void)sprintf(out_val, "You have destroyed %s.", m_name);
  2606.         else
  2607.         (void)sprintf(out_val, "You have slain %s.", m_name);
  2608.         msg_print(out_val);
  2609.         prt_experience();
  2610.     } else {
  2611.         m_name[0] = toupper((int)m_name[0]);    /* Capitalize */
  2612.     /* Can not stun Balrog */
  2613.         avg_max_hp = (c_ptr->cdefense & MAX_HP ?
  2614.               c_ptr->hd[0] * c_ptr->hd[1] :
  2615.               (c_ptr->hd[0] * (c_ptr->hd[1] + 1)) >> 1);
  2616.         if ((100 + randint(400) + randint(400))
  2617.         > (m_ptr->hp + avg_max_hp)) {
  2618.         m_ptr->stunned += randint(3) + 1;
  2619.         if (m_ptr->stunned > 24)
  2620.             m_ptr->stunned = 24;
  2621.         (void)sprintf(out_val, "%s appears stunned!", m_name);
  2622.         } else
  2623.         (void)sprintf(out_val, "%s ignores your bash!", m_name);
  2624.         msg_print(out_val);
  2625.     }
  2626.     } else {
  2627.     (void)sprintf(out_val, "You miss %s.", m_name);
  2628.     msg_print(out_val);
  2629.     }
  2630.     if (randint(150) > py.stats.use_stat[A_DEX]) {
  2631.     msg_print("You are off balance.");
  2632.     py.flags.paralysis = 1 + randint(2);
  2633.     }
  2634. }
  2635.  
  2636.  
  2637. /* Bash open a door or chest                -RAK-     */
  2638. /*
  2639.  * Note: Affected by strength and weight of character 
  2640.  *
  2641.  * For a closed door, p1 is positive if locked; negative if stuck. A disarm
  2642.  * spell unlocks and unjams doors! 
  2643.  *
  2644.  * For an open door, p1 is positive for a broken door. 
  2645.  *
  2646.  * A closed door can be opened - harder if locked. Any door might be bashed open
  2647.  * (and thereby broken). Bashing a door is (potentially) faster! You move
  2648.  * into the door way. To open a stuck door, it must be bashed. A closed door
  2649.  * can be jammed (which makes it stuck if previously locked). 
  2650.  *
  2651.  * Creatures can also open doors. A creature with open door ability will (if not
  2652.  * in the line of sight) move though a closed or secret door with no changes.
  2653.  * If in the line of sight, closed door are openned, & secret door revealed.
  2654.  * Whether in the line of sight or not, such a creature may unlock or unstick
  2655.  * a door. 
  2656.  *
  2657.  * A creature with no such ability will attempt to bash a non-secret door. 
  2658.  */
  2659. void 
  2660. bash()
  2661. {
  2662.     int                 y, x, dir, tmp;
  2663.     register cave_type *c_ptr;
  2664.     register inven_type *t_ptr;
  2665. #ifdef TARGET
  2666.     int temp = target_mode; /* targetting will screw up get_dir, so we save
  2667.                    target_mode, then turn it off -CFT */
  2668. #endif
  2669.  
  2670.     y = char_row;
  2671.     x = char_col;
  2672. #ifdef TARGET
  2673.     target_mode = FALSE;
  2674. #endif
  2675.     if (get_dir(NULL, &dir)) {
  2676.     if (py.flags.confused > 0) {
  2677.         msg_print("You are confused.");
  2678.         do {
  2679.         dir = randint(9);
  2680.         }
  2681.         while (dir == 5);
  2682.     }
  2683.     (void)mmove(dir, &y, &x);
  2684.     c_ptr = &cave[y][x];
  2685.     if (c_ptr->cptr > 1) {
  2686.         if (py.flags.afraid > 0)
  2687.         msg_print("You are too afraid!");
  2688.         else
  2689.         py_bash(y, x);
  2690.     } else if (c_ptr->tptr != 0) {
  2691.         t_ptr = &t_list[c_ptr->tptr];
  2692.         if (t_ptr->tval == TV_CLOSED_DOOR) {
  2693.         count_msg_print("You smash into the door!");
  2694.         tmp = py.stats.use_stat[A_STR] + py.misc.wt / 2;
  2695.         /* Use (roughly) similar method as for monsters. */
  2696.         if (randint(tmp * (20 + abs((int) t_ptr->p1))) <
  2697.             10 * (tmp - abs((int) t_ptr->p1))) {
  2698.             msg_print("The door crashes open!");
  2699.             invcopy(&t_list[c_ptr->tptr], OBJ_OPEN_DOOR);
  2700.             t_ptr->p1 = 1 - randint(2);    /* 50% chance of breaking door */
  2701.             c_ptr->fval = CORR_FLOOR;
  2702.             if (py.flags.confused == 0)
  2703.             move_char(dir, FALSE);
  2704.             else
  2705.             lite_spot(y, x);
  2706.             check_view();
  2707.         } else if (randint(150) > py.stats.use_stat[A_DEX]) {
  2708.             msg_print("You are off-balance.");
  2709.             py.flags.paralysis = 1 + randint(2);
  2710.         } else if (command_count == 0)
  2711.             msg_print("The door holds firm.");
  2712.         } else if (t_ptr->tval == TV_CHEST) {
  2713.         if (randint(10) == 1) {
  2714.             msg_print("You have destroyed the chest and its contents!");
  2715.             t_ptr->index = OBJ_RUINED_CHEST;
  2716.             t_ptr->flags = 0;
  2717.         } else if ((CH_LOCKED & t_ptr->flags) && (randint(10) == 1)) {
  2718.             msg_print("The lock breaks open!");
  2719.             t_ptr->flags &= ~CH_LOCKED;
  2720.         } else
  2721.             count_msg_print("The chest holds firm.");
  2722.         } else
  2723.         /*
  2724.          * Can't give free turn, or else player could try directions
  2725.          * until he found invisible creature 
  2726.          */
  2727.         msg_print("You bash it, but nothing interesting happens.");
  2728.     } else {
  2729.         if (c_ptr->fval < MIN_CAVE_WALL)
  2730.         msg_print("You bash at empty space.");
  2731.         else
  2732.         /* same message for wall as for secret door */
  2733.         msg_print("You bash it, but nothing interesting happens.");
  2734.     }
  2735.     }
  2736. #ifdef TARGET
  2737.     target_mode = temp;
  2738. #endif
  2739. }
  2740.  
  2741. static const char        *
  2742. look_mon_desc(mnum)
  2743.     int                 mnum;
  2744. {
  2745.     monster_type       *m = &m_list[mnum];
  2746.     int32               thp, tmax, perc;
  2747.     int8u               living = !((c_list[m->mptr].cdefense & (UNDEAD | DEMON)) ||
  2748.                    c_list[m->mptr].cchar == 'E');
  2749.  
  2750.     if (m->maxhp == 0) {       /* then we're just going to fix it! -CFT */
  2751.     if ((c_list[m->mptr].cdefense & MAX_HP) || be_nasty)
  2752.         m->maxhp = max_hp(c_list[m->mptr].hd);
  2753.     else
  2754.         m->maxhp = pdamroll(c_list[m->mptr].hd);
  2755.     }
  2756.     if (m->hp > m->maxhp)
  2757.     m->hp = m->maxhp;
  2758.  
  2759.     if ((m->maxhp == 0) || (m->hp >= m->maxhp))    /* shouldn't ever need > -CFT */
  2760.     return (living ? "unhurt" : "undamaged");
  2761.     thp = (int32) m->hp;
  2762.     tmax = (int32) m->maxhp;
  2763.     perc = (int32) (thp * 100L) / tmax;
  2764.     if (perc > 60)
  2765.     return (living ? "somewhat wounded" : "somewhat damaged");
  2766.     if (perc > 25)
  2767.     return (living ? "wounded" : "damaged");
  2768.     if (perc > 10)
  2769.     return (living ? "badly wounded" : "badly damaged");
  2770.     return (living ? "almost dead" : "almost destroyed");
  2771. }
  2772.  
  2773. #ifdef TARGET
  2774. /* This targetting code stolen from Morgul -CFT */
  2775. /* Targetting routine                     CDW */
  2776. void
  2777. target()
  2778. {
  2779.     int monptr,exit,exit2;
  2780.     char query;
  2781.     vtype desc;
  2782.  
  2783.     exit = FALSE;
  2784.     exit2 = FALSE;
  2785.     if (py.flags.blind > 0)
  2786.     msg_print("You can't see anything to target!");
  2787.     /* Check monsters first */
  2788.     else {
  2789.     target_mode = FALSE;
  2790.     for (monptr = 0; (monptr<mfptr) && (!exit); monptr++) {
  2791.         if (m_list[monptr].cdis<MAX_SIGHT) {
  2792.         if ((m_list[monptr].ml)&&
  2793.             (los(char_row,char_col,m_list[monptr].fy,m_list[monptr].fx))) {
  2794.             move_cursor_relative(m_list[monptr].fy,m_list[monptr].fx);
  2795.             (void) sprintf(desc, "%s [(r)ecall] [(t)arget] [(l)ocation] [ESC quits]",
  2796.                    c_list[m_list[monptr].mptr].name);
  2797.             prt(desc,0,0);
  2798.             move_cursor_relative(m_list[monptr].fy,m_list[monptr].fx);
  2799.             query = inkey();
  2800.             while ((query == 'r')||(query == 'R')) {
  2801.             save_screen();
  2802.             query = roff_recall(m_list[monptr].mptr);
  2803.             restore_screen();
  2804.             move_cursor_relative(m_list[monptr].fy,m_list[monptr].fx);
  2805.             query = inkey();
  2806.             }
  2807.             switch (query) {
  2808.             case ESCAPE:
  2809.             exit = TRUE;
  2810.             exit2 = TRUE;
  2811.             break;
  2812.             case '.':    /* for NetHack players, '.' is used to select a target,
  2813.                    so I'm changing this... -CFT */
  2814.             case 't': case 'T':
  2815.             target_mode = TRUE;
  2816.             target_mon  = monptr;
  2817.             target_row  = m_list[monptr].fy;
  2818.             target_col  = m_list[monptr].fx;
  2819.             exit2 = TRUE;
  2820.             case 'l': case'L':
  2821.             exit = TRUE;
  2822.             default:
  2823.             break;
  2824.             }
  2825.         }
  2826.         }
  2827.     }
  2828.     if (exit2 == FALSE) {
  2829.         prt("Use cursor to designate target. [(t)arget]",0,0);
  2830.         target_row = char_row;
  2831.         target_col = char_col;
  2832.         for (exit = FALSE; exit==FALSE ;) {
  2833.         move_cursor_relative(target_row, target_col);
  2834.         query=inkey();
  2835.         if (rogue_like_commands==FALSE) {
  2836.             switch (query) {
  2837.             case '1':
  2838.             query = 'b';
  2839.             break;
  2840.             case '2':
  2841.             query = 'j';
  2842.             break;
  2843.             case '3':
  2844.             query = 'n';
  2845.             break;
  2846.             case '4':
  2847.             query = 'h';
  2848.             break;
  2849.             case '5':
  2850.             query = '.';
  2851.             case '6':
  2852.             query = 'l';
  2853.             break;
  2854.             case '7':
  2855.             query = 'y';
  2856.             break;
  2857.             case '8':
  2858.             query = 'k';
  2859.             break;
  2860.             case '9':
  2861.             query = 'u';
  2862.             break;
  2863.             default:
  2864.             break;
  2865.             }
  2866.         }
  2867.         switch (query) {
  2868.         case ESCAPE:
  2869.             case'q':
  2870.         case 'Q':
  2871.             exit = TRUE;
  2872.             break;
  2873.         case '.':    /* for NetHack players, '.' is used to select a target,
  2874.                    so I'm changing this... -CFT */
  2875.         case 't':
  2876.         case 'T':
  2877.             if (distance(char_row,char_col,target_row,target_col)>MAX_SIGHT)
  2878.             prt(
  2879.                 "Target beyond range. Use cursor to designate target. [(t)arget].",
  2880.                 0,0);
  2881.             else if (cave[target_row][target_col].fval>CORR_FLOOR)
  2882.             prt(
  2883.                 "Invalid target. Use cursor to designate target. [(t)arget].",
  2884.                 0,0);
  2885.             else {
  2886.             target_mode = TRUE;
  2887.             target_mon  = MAX_MALLOC;
  2888.             exit = TRUE;
  2889.             }
  2890.             break;
  2891.         case 'b':
  2892.             target_col--;
  2893.         case 'j':
  2894.             target_row++;
  2895.             break;
  2896.         case 'n':
  2897.             target_row++;
  2898.         case 'l':
  2899.             target_col++;
  2900.             break;
  2901.         case 'y':
  2902.             target_row--;
  2903.         case 'h':
  2904.             target_col--;
  2905.             break;
  2906.         case 'u':
  2907.             target_col++;
  2908.         case 'k':
  2909.             target_row--;
  2910.             break;
  2911.         default:
  2912.             break;
  2913.         }
  2914.         if ((target_col>MAX_WIDTH-2)||(target_col>panel_col_max))
  2915.             target_col--;
  2916.         else if ((target_col<1)||(target_col<panel_col_min))
  2917.             target_col++;
  2918.         if ((target_row>MAX_HEIGHT-2)||(target_row>panel_row_max))
  2919.             target_row--;
  2920.         else if ((target_row<1)||(target_row<panel_row_min))
  2921.             target_row++;
  2922.         
  2923.         }
  2924.     }
  2925.     if (target_mode==TRUE)
  2926.         msg_print("Target selected.");
  2927.     else
  2928.         msg_print("Aborting Target.");
  2929.     }
  2930. }
  2931.  
  2932. /* This targetting code stolen from Morgul -CFT */
  2933. /* Assuming target_mode == TRUE, returns if the position is the target.
  2934.                         CDW */
  2935. int
  2936. at_target(row,col)
  2937.      int row,col;
  2938. {
  2939.     if (target_mode == FALSE) return FALSE; /* don't ever assume a condition
  2940.                            holds, especially when it's so easy to test
  2941.                            for. -CFT */
  2942.     if ((row==target_row)&&(col==target_col))
  2943.     return(TRUE);
  2944.     else
  2945.     return(FALSE);
  2946. }
  2947. #endif /* TARGET */
  2948.  
  2949. void 
  2950. mmove2(y, x, sourcey, sourcex, desty, destx)
  2951.     register int       *y, *x;
  2952.     int                 sourcey, sourcex, desty, destx;
  2953. {
  2954.     int                 d_y, d_x, k, dist, max_dist, min_dist, shift;
  2955.  
  2956.     d_y = (*y < sourcey) ? sourcey - *y : *y - sourcey;
  2957.     d_x = (*x < sourcex) ? sourcex - *x : *x - sourcex;
  2958.     dist = (d_y > d_x) ? d_y : d_x;
  2959.     dist++;
  2960.     d_y = (desty < sourcey) ? sourcey - desty : desty - sourcey;
  2961.     d_x = (destx < sourcex) ? sourcex - destx : destx - sourcex;
  2962.     if (d_y > d_x) {
  2963.     max_dist = d_y;
  2964.     min_dist = d_x;
  2965.     } else {
  2966.     max_dist = d_x;
  2967.     min_dist = d_y;
  2968.     }
  2969.     for (k = 0, shift = max_dist >> 1; k < dist; k++, shift -= min_dist)
  2970.     shift = (shift > 0) ? shift : shift + max_dist;
  2971.     if (shift < 0)
  2972.     shift = 0;
  2973.  
  2974.     if (d_y > d_x) {
  2975.     d_y = (desty < sourcey) ? *y - 1 : *y + 1;
  2976.     if (shift)
  2977.         d_x = *x;
  2978.     else
  2979.         d_x = (destx < sourcex) ? *x - 1 : *x + 1;
  2980.     } else {
  2981.     d_x = (destx < sourcex) ? *x - 1 : *x + 1;
  2982.     if (shift)
  2983.         d_y = *y;
  2984.     else
  2985.         d_y = (desty < sourcey) ? *y - 1 : *y + 1;
  2986.     }
  2987.     *y = d_y;
  2988.     *x = d_x;
  2989. }
  2990.